Guest Post: Nth Occurrence DAX Formula

March 31, 2011

David Hager is At It Again

A short two weeks after his truly creative Measure Catalog Macro post, David Hager is back with a heavyweight DAX post.

This time he is exploring an area of the product that I have very little experience with, namely the EARLIER() function.  On the DAX spicy scale, EARLIER() is a 5 in my opinion, but the other reason I haven’t done much with it is because I’m pretty sure it’s only useful in calc columns.  At Pivotstream we do all of our calc columns in SQL (for several reasons I won’t go into here).

But not everyone has colleagues ready to write calc columns in SQL for them now do they?  In fact, the Great PowerPivot Survey is reinforcing that for me (I’m going to wait until next week before I start summarizing results, but it sure has been interesting so far).

OK David, take it away.

CREATING AN Nth OCCURRENCE DAX FORMULA

By David Hager

CLICK HERE TO DOWNLOAD THE WORKBOOK IN THIS POST

When you have a growing database of customer records (such as purchases at a store), it is useful to have a method for tracking the previous visit for each customer.

A formula of the following type can be used for this.

=CALCULATE(MAX(Table1[DATE]),FILTER(Table1, EARLIER(Table1[Customer])=Table1[Customer] && EARLIER(Table1[DATE])>Table1[DATE]))

(See http://gavinrussell.wordpress.com/2010/09/23/powerpivot-dax-session-notes-2-previous-row/ for the original idea behind this post).

image

However, note that the previous visit date is returned for every customer visit (except the initial one) for each customer. In some cases, this may be the desired result, but usually only the last customer visit record would add the previous visit as useful information.

While trying to make a formula that would do this, I thought that it would also be nice if I could expand that concept to find an Nth previous visit. Since I did not want to hard-code an Nth value that would have to be updated manually in the PowerPivot cube, I had to invent a method for creating a dynamic constant.

In order to create a dynamic constant for PowerPivot (which would simply be an updatable cell value in Excel), the first step is to create an Excel table. The table consists of a Date field which can be used to create a relationship with the fact table Date field and a constant field. In each row of the constant field, the same formula needs to point to the update cell (=$D$2).

image

Now, the table can be linked to PowerPivot, using the Create Linked Table feature.

Note from Rob:  Here’s another great example of a feature that I never use (Linked Table), because that linkage doesn’t refresh on the server.  But it has tremendous utility in desktop PowerPivot, so I’m glad David is showing it off here.

Two more steps remain before the dynamic constant can be used in a calculated column formula. By clicking Create Relationship in the PowerPivot window Design ribbon, a relationship can be established between the Date field in Table1 with the same in Table2. Finally, a calculated column named NTH is added to Table1 with the formula =RELATED(Table2[NTH]).

Now it is time to create the formula. The entire version of this formula is too complex to be viewed in a completely displayed form, so two parts of it are entered as calculated columns and are used as inputs into the formula shown below.

=IF(Table1[IsLastRecord],CALCULATE(MAX(Table1[DATE]),FILTER(Table1,EARLIER(Table1[Customer])=

Table1[Customer] && EARLIER(Table1[DATE])>Table1[DATE] &&Table1[IsNthPreviousRecord])),BLANK())

where

Table1[IsLastRecord]

=COUNTROWS(FILTER(Table1,EARLIER(Table1[Customer])=Table1[Customer]))=

(COUNTROWS(FILTER(Table1, EARLIER(Table1[Customer])=Table1[Customer] && EARLIER(Table1[DATE])>Table1[DATE]))+1)

and

Table1[IsNthPreviousRecord]

=(COUNTROWS(FILTER(Table1,EARLIER(Table1[Customer])=Table1[Customer]))-

(COUNTROWS(FILTER(Table1, EARLIER(Table1[Customer])=Table1[Customer] &&

EARLIER(Table1[DATE])>Table1[DATE]))+1)=Table1[NTH])

IsLastRecord counts the numbers of records for each customer and compares that number to the number of records previous to the last record plus 1. If the numbers are the same, the expression is true and the last record in row context for each customer will have a date depending on whether it had an Nth previous visit (otherwise a blank).

IsNthPreviousRecord is the 3rd filter in the main DAX formula. This Boolean expression is true if the numbers of records for each customer minus number of records previous to the last record plus 1 is equal to the desired Nth previous visit.

The following picture shows the returned records for the table example when Nth is equal to 2.

image

Note that only customers a & d have 3 or more visits, so those are the only dates returned.

I have not gone into great detail into explaining exactly how this DAX formula works mainly because if you work through this yourself you will gain a greater understanding of how to construct your own formulas. Note from Rob:  Heh heh, now I STILL don’t understand EARLIER().  Nor have I built a pivot table that exploits the power of this formula. I will also leave that as an exercise to the reader.

As you might imagine, there are many ways that this formula methodology for Nth occurrence can be used. Also, the technique for using a dynamic constant is pretty neat. I hope this helps in your future PowerPivot model-building projects!


Announcing the Great PowerPivot Survey

March 28, 2011

 
Click Here to Take The Great PowerPivot Survey

We don't want to THINK.  We want to KNOW.

“We don’t want to THINK.  We want to KNOW.”

A few days ago, on the FAQ page, David Vella was asking some questions about PowerPivot, including PowerPivot adoption.  If you’d like to see his questions, and my answers, you can see the whole exchange here, but below I’ve excerpted a portion of my reply:

“Other than Pivotstream’s own heavy usage, I didn’t see signs of significant real-world deployments until roughly September of 2010. Adoption slowly crept up through the end of the year, and then really took off in January. Blog traffic is up about 30%, and more telling is that new clients reach out to us at about 5x the rate of last year.

The one place where I think adoption is slower than desired, ironically, is with Excel users. What I am seeing is a lot of enthusiastic top-down adoption, and very little bottom-up adoption. By the time PowerPivot reaches its entire target audience (millions upon millions of Excel power users), I expect to see blog traffic at about 100x (or more) of what I have today. So there is a long way to go with that crowd. But the top-down crowd is gaining steam in a big way.”

After I wrote that, it struck me that it would be useful (for all of us) to have more data on this beyond my own experience.

So, without further ado, here it is:

Click Here to Take The Great PowerPivot Survey

image

It should take you 5 minutes or less.  I will summarize the results here on the blog when the survey closes.


Advanced DAX calculation: doing a moving grouped average in PowerPivot

March 24, 2011

Woops I'm sorry, did I change your Filter Context ?

By Kasper de Jonge, original post at PowerPivotblog.nl

I got an excellent question last week on the ask my question page that brought me new understanding of DAX. So finally a new interesting (I hope) blog post on DAX.

Let’s say I have a set of sales per week of a specific brand:

Now I want to have the average of sales per week (slicable by brand) and compare it to the average of the last 3 weekly totals. I prepare  the pivottable :

Read the rest of this entry »


Are you making daiquiris or blenders?

March 23, 2011

 
PowerPivot is a Daiquiri Traditional BI is a Blender

A Lasting Metaphor

Many years ago, I was designing a feature for Excel 2003.  And the VP of our division of Office, a man named Richard McAniff, didn’t like the feature.  At one point, he told me:

“Rob, it’s like you live in a world where everyone wants really tasty daiquiris.  And what you are building is a blender.  A blender that, when assembled and used properly, can make great daiquiris.  But the problem is, no one wants the blender.  They don’t want to mess with it, they’re too busy for that.  What they want…  is just the tasty daiquiri.”

Now actually, when Richard said that, he used the metaphor of “ovens and steaks” rather than “blenders and daiquiris.”  Which always seemed a bit “off” to me – I mean, who cooks steaks in the oven?  For a middle class guy like me, steaks are cooked on a grill.  But the funny truth is that the most expensive steaks DO get cooked in ovens.  His wise metaphor was diluted by too many years spent at his payscale.  (Richard, I love you man, and someday hope to have enough money that I will no longer detect such idiosyncrasies, heh heh).  So…  I am “translating” the metaphor, which I have used for many years now.

Blenders ARE necessary, but they shouldn’t become the GOAL

This has tremendous relevance to the way in which PowerPivot is turning the BI industry on its head.

The genesis of any BI initiative is the desire to know more about your business.  The goal is Better Insight.  But what happens next?  You immediately get sidetracked/hijacked into Building an Infrastructure.  Massive investments in Data Warehousing.  Master Data Management.  Extract, Transform, and Load.  Heavy, heavy stuff.

Now, is that stuff necessary?  Yes, but only to an extent.  The problem is with the sequence – first you build out tons of infrastructure.  And then you start delivering insights.

Well guess what?  It takes about five minutes for the desired Insights to fade into the background, and for the Infrastructure to become a goal in itself.

That’s really, REALLY dangerous stuff.  As I’ve pointed out before, you often don’t even know that your requirements are flawed until you see your first visualization.  Months of infrastructure work could deliver something that falls dramatically short in critical areas.  And at the same time, the infrastructure might vastly over-deliver on certain aspects that turn out not to be all that needed.

The Entire Industry is Built This WaySensitive Systems

As flawed as that approach may be, in many ways, technology wasn’t ready to support doing it a different way until recently.

Now that a better way is available, though, we’re still very early in the transition.  Nearly everything about the BI industry is still geared around the old way, to the extent that today’s tools and processes actually require those huge infrastructure investments.  They are so tuned to the painstaking way that you can’t just start speeding things up.

It reminds me of the sensitivity of US modern fighter jets.  Every morning, the crews have to walk the entire length of the runway, in a line spanning its width, looking for little pebbles and other debris that could seriously damage the aircraft.  These are machines built for WAR, but they can’t handle pebbles.

Dive InA Better Way:  Just Get Started!

Don’t have the perfect infrastructure/blender built yet?  Great – that means you have wasted no time to date!  Just get started.  Load some data into PowerPivot.  You can even load it from multiple sources, all into one model.  Experiment.  See what you can learn from the data in its current form.

Nothing exposes the flaws in your data sources quite like this process.  You WILL find problems in your source data that need to be fixed.  But then you can go focus on fixing JUST those, and you will know precisely what the fix needs to look like.  You can be very prescriptive about it, and limit the scope of the work.  Often, the fix takes less than five minutes.  (And yes, other times, it’s an overhaul).

Inverting the Traditional Sequence:  Keeping the Desired Result in Focus

Traditional BI’s sequence:

  1. Develop a broad plan that encompasses all or most of the important data sources in your organization.
  2. Embark on an often-lengthy process of developing shared standards across all of those data sources.
  3. Write endless amounts of logic to load and transform data into a Data Warehouse.
  4. Embark on the process of building cubes over the top of the DW, encoding complex business rules (explained to the techies by the business users) into measure calculations.
  5. Produce the first visualizations and reports.
  6. Collect feedback from all of the unsatisfied consumers, and use that as feedback to start over at step 1.

The Sequence that PowerPivot Enables:

  1. Pick a business question or need that is currently unaddressed.  Set your goal as “let’s answer that, right now.”
  2. If you have an existing DW, use it.  If not, start from existing data sources.  A good middle ground is to shape your sources into Star Schemas, which is relatively simple compared to building a full-fledged DW.
  3. Load data into PowerPivot.
  4. Build charts and reports.  Write measures as needed.  See how far you get.
  5. If you discover that you need data source changes, go and get those done.  May take a few iterations but it will still be light years faster than the traditional process.
  6. Pick another business question.  Dive in.  Repeat.

You’ll be stunned at how far you get, and how fast.

Another Example of the Metaphor in Action

The trigger for this blog post was a conversation I had yesterday about field lists.  Field lists are very much a necessary tool for building reports and visualizations.

Of course, 99% of the world never wants to see a field list.  And I can’t blame them.  Field lists are blenders.  The reports/visualizations themselves are the daiquiris.

Field List is a Blender   Visualizations are Daiquiris

The message I tried to convey in that chat (and poorly, I might add) is that field lists are a difficult thing to sell to most people, as compared to the finished product they produce.

That’s why I try to start every presentation on PowerPivot with a demo of a finished, published, interactive report, before trying to show anyone the addin.  And it’s also one reason why Pivotstream’s subscription BI business goes over so well – no field lists, no infrastructure.  No blenders.  Just insights and daiquiris.

Parting thought

As someone who makes his living off of software, I obviously make blenders whether I like it or not.  If you are reading this, chances are that you do too.

The key is to remember that blenders don’t sell, because your customers rightfully aren’t interested in buying more infrastructure.  Their eyes are on the prize.  So the more you can think like them, and focus on the same goals that they have, the better you will do.

And I’m not just talking about marketing spin.  I firmly believe that daiquiri-focused engineers build much better blenders than blender-focused engineers.

OK, back to DAX tricks in the next post.


Guest Post: Catalog Your Measures with a Nifty Macro

March 16, 2011

 
UPDATE:  Uploaded a new version of the macro file that David provided that fixed a couple of small problems.  Also, I fixed a typo (I had it as XSLM, not XLSM – thanks Dan!)

We have a guest post today from David Hager.  Like most folks who exchange email with me, David is now aware of how… intermittent… an enterprise that is.  Intermittent being the description of the replies one receives.

But he persevered.  And this is a pretty ingenious macro he has written.

So ingenious, in fact, that he is bordering on revealing a few techniques that I have been debating whether or not to unmask.  Things we do at Pivotstream that Microsoft considers unsupported.  Which, of course, is the good stuff.  David is traipsing around in some very dark corners.

The only clarification I will offer to his post, which appears below, is the following:  When David says “this procedure finds where the measures are stored in the PowerPivot workbook,” I want to make clear that what is being found is actually where PowerPivot keeps a backup copy of the measures.  The backup copy is always up to date, so it is very much reliable.

But the “real”definitions are actually stored elsewhere, in a place named Item1.data – and, like Forrest Gump, that’s all I have to say about that.

Take it away David…

Creating a Measures Table From PowerPivot Workbooks in a Folder

By David Hager

When defined name formulas are added to an Excel workbook, they can be easily accessed and viewed through the use of Excel’s Name Manager. However, when measures (formulas added to PowerPivot pivot tables and based on the DAX query language) are created, there is no way to know that they exist except for visually scanning the PowerPivot field list. An icon resembling a calculator will be to the right of each formula created in the field list. However, in order to view the DAX formula, the field must be right-clicked and “Edit Measure” selected. Then, if you wanted to store that measure somewhere for future reference, it can be copy/pasted to the desired location. This process becomes time-consuming if you have many PowerPivot workbooks that contain many measures. It would be nice if that process could be automated. To that end, the following VBA procedure for opening files in a folder and extracting the DAX measures and putting them in a table can be downloaded here.

(NOTE FROM ROB:  You MUST rename that file to .XLSM before you can open it!  WordPress does not allow upload of macro-enabled files, so I uploaded as XLSX.  And if you don’t trust macros from other people, I respect that.  Maybe we’ll upload a text only version with instructions for those of you in that camp.)

Most of the code deals with file and folder manipulation, and will not be discussed here. The core procedure is shown below.

Sub ExtractAndCopyMeasures()
Dim tText As String
Dim strStart As Long
Dim sCopy As String
Dim sCopyArray
Dim aCol As Range
Dim bCol As Range
Dim sItem

On Error Resume Next

tText = ActiveWorkbook.CustomXMLParts("http://gemini/workbookcustomization/MetadataRecovery _Information").XML

strStart = CLng(InStr(1, tText, "CREATE MEASURE"))
sCopy = Mid(tText, strStart, InStr(strStart, tText, "</") – strStart – 2)
sCopy = Replace(sCopy, " ", "")
sCopy = Replace(sCopy, Chr(10), "")
sCopy = Replace(sCopy, "&lt;", "<")
sCopy = Replace(sCopy, "&gt;", ">")
sCopyArray = Split(sCopy, ";")

For Each sItem In sCopyArray

  Set aCol = ThisWorkbook.Worksheets("MeasureTable").Range("a1048576").End(xlUp).Offset(1, 0)
  Set bCol = ThisWorkbook.Worksheets("MeasureTable").Range("b1048576").End(xlUp).Offset(1, 0)
  aCol.Value = ActiveWorkbook.FullName
  bCol.Value = Mid(sItem, InStr(1, sItem, ".") + 1)

Next

End Sub

In essence, this procedure finds where the measures are stored in the PowerPivot workbook, parses the measures and place them in a table. Now, let’s examine some key parts of the code.

tText = ActiveWorkbook.CustomXMLParts("http://gemini/workbookcustomization/MetadataRecovery _Information").XML

This line loads into a variable the XML from the custom XML part in the workbook that contains the measures.

strStart = InStr(1, tText, "CREATE MEASURE")

This is the position in the XML string where the first measure is located.

sCopy = Mid(tText, strStart, InStr(strStart, tText, "</") – strStart – 2)

This code locates and stores just the part of the XML string that contains the measures.

sCopy = Replace(sCopy, " ", "")
sCopy = Replace(sCopy, Chr(10), "")
sCopy = Replace(sCopy, "&lt;", "<")
sCopy = Replace(sCopy, "&gt;", ">")

These lines of code clean up the string so that the formulas can be properly displayed. In particular, the terms "&lt;" and "&gt;" are used in XML for “<” and “>” respectively to prevent reading errors.

sCopyArray = Split(sCopy, ";")

The Split function converts the delimited string into a variant array containing each measure as an item in the array.

For Each sItem In sCopyArray

  Set aCol = ThisWorkbook.Worksheets("MeasureTable").Range("a1048576").End(xlUp).Offset(1, 0)
  Set bCol = ThisWorkbook.Worksheets("MeasureTable").Range("b1048576").End(xlUp).Offset(1, 0)
  aCol.Value = ActiveWorkbook.FullName
  bCol.Value = Mid(sItem, InStr(1, sItem, ".") + 1)

Next

The final part of the procedure loops through the array. aCol is used to set the next empty row without using a counter. The measure is extracted from the array item by using Mid(sItem, InStr(1, sItem, ".") + 1) to start at the correct string postion.

I hope that you find this procedure useful!

Note: There may be some prompts that will have to be answered manually during the file opening process.


More Fun With IF(VALUES())

March 12, 2011

 
Cast of Superbad:  Clearly watching a video on amazing PowerPivot DAX techniques

“I mean, IF() I’m paying top dollar, I want a little production VALUE()”

I bet you thought I was out of movie quotes for IF(VALUES()) didn’t you!  If I had a fake ID, my name would be “McPivot.”

Bag of Tricks

OK, once you have a reasonable level of comfort with the workings of IF(VALUES()), whether that comfort is “I understand it” or even just “I can make it give me the right results,” you are in for some treats.  There are a number of ways to use IF(VALUES()) to produce different desired effects.  I’m going to blast through a few of them here real quick.

Note:  If you have not read the previous post, you should do so before reading this one.

Returning BLANK() for Subtotals and Grand Totals

Sometimes you end up with a measure that simply doesn’t make sense unless you are in the context of a single item.  Returning to the football project, let’s say I write a measure that for “Personal Best Single Game Rushing Yards,” which, for a given football player, returns their personal best single-game total over all time:

Best Single Week Performance Measure in PowerPivot

Cool huh?  (My data ends before Adrian Peterson broke Jamal Lewis’ record).  By the way, the formula for that measure is:

   =MAXX(ALL(DimProschedule[GameDate]),[Rushing Yards])

(To understand how that measure works, I refer you to one of my personal favorite posts, the Five-Point-Palm, Exploding Function Technique.)

Now, if you put another field on the pivot, you have a decision to make:  do you want that measure to be evaluated at levels other than a single player?  How about for an entire team?  Or all players of a given position?  You may decide that doesn’t make sense, and prefer that the measure NEVER return a value in those cases.

Good thing we have IF(VALUES()).  We can create another measure based on the existing measure:

   =IF(COUNTROWS(VALUES( CleanPlayers[PlayerID] ))=1,
       [Best Single Gm Rush Yds], BLANK())

Best Single Week Performance But Player Only Measure in PowerPivot

Notice how the original measure does not reflect the best player total?  In the week that Lewis ran for 295, apparently the Ravens had other players run for a total of 39 additional yards.  Depending on the semantics desired, you could argue that the Ravens’ number should be 295, for best single player performance in a game.

Or you can just return blank and forget about it, as my second measure does.

Returning different measures for different cases (aka “Branching”)

If we look at the picture above, you may say “hey it’s not fair to compare QB’s against RB’s in rushing yards, shouldn’t each position be measured by its primary metric – pass yards for QB, rush yards for RB, and receiving yards for WR’s and TE’s?”

Yeah, let’s do that.  First let’s create similar “best game ever” measures for the other two kinds of yardage – passing (throwing) and receiving (catching).  (Rushing is running, btw).

Best Single Week Performance All Three Measures in PowerPivot

OK, cool, so we have all three measures, but it results in a scraggly pivot.  I want a single column of numbers, and for the number to reflect the position (primary role) of the particular player.

IF(VALUES()) to the rescue.  A new measure that “branches” into the right measure for each position:

   =IF(COUNTROWS(VALUES( CleanPlayers[PlayerID] ))=1,
      IF(VALUES(CleanPlayers[PositionCode])="QB", [Best Single Game Pass Yards],
      IF(VALUES(CleanPlayers[PositionCode])="RB", [Best Single Game Rush Yards],
      IF(VALUES(CleanPlayers[PositionCode])="WR", [Best Single Game Rec Yards],
      IF(VALUES(CleanPlayers[PositionCode])="TE", [Best Single Game Rec Yards],
      BLANK())
      ))),
      BLANK()
   )

Best Single Week Performance Branching Measure in PowerPivot

Cool, huh?  A few things to note:

  1. IF(VALUES()) is used to check the value of [PositionCode], but [PositionCode] isn’t even on the pivot!  This works because each PlayerID does correspond, in the CleanPlayers table, to a single position code, because each PlayerID is unique.
  2. That said, it IS hard to tell which player is which position, especially for the 49ers, who had awful teams during the years for which I have data.  So I’ll add Position to the pivot below.
  3. I’m pretty sure that Johnnie Morton had his 153 yard receiving day when he played for the Lions, not the 49ers, but solving that problem is best saved for another day.

Here’s the pivot with position added in for clarity:

Best Single Week Performance Branching Measure in PowerPivot 2

(I decided to screenshot the Bears section rather than 49ers because the Bears had better players in those years.)


The Magic of IF(VALUES())

March 9, 2011

 
Dan Marino Wraps His VALUEs in IFs and So Should You

“I’m Dan Marino, and IF() anyone knows the VALUE() of protection, it’s me.”

Boom!  An Ace Ventura quote finally graces the blog.  Yes folks, that fine work of American cinema did indeed feature Dan Marino reprising his real-world ad for Isotoner.

 

(UPDATE:  I had the val_if_true, val_if_false arguments reversed in my sample formulas, even though I had them correct in Excel.  I’m rusty Smile.  Fixed now.)

But more importantly, I wanted to revisit this little two-function combo:  IF(VALUES()).  I’ve covered it before a few times, but generally in the context of covering something else.

And since this is one of my favorite techniques, I think it deserves its own dedicated post.  A series of posts, actually.  Let’s dig in.

In Measures, You Can’t Just use IF()!

In regular Excel, the IF() function is a familiar tool to most of us:

      IF(logical_test, value_if_true, value_if_false)

In PowerPivot, you can use precisely that same version of IF() in calculated columns.  So, for example:

      IF(Table1[Column1]>6, 0, 1)

In a measure formula, however, you cannot do that.  If you do, you will receive the following error:

PowerPivot Error Value for Column Cannot be Determined in the Current Context

PowerPivot Error Value for Column Cannot be Determined in the Current Context

To better understand why that happens, let’s get ourselves an example…

“Whoa, did you say DimDown???”

Yeah that’s right, the Great Football Project is back after a long hiatus! I had a phone call yesterday with a Pittsburgh Steelers fan.  You know Pittsburgh?  It’s a drinking town with a football problem.

Anyway, he requested a return to the football project, under the umbrella of “how do the Steelers win another Super Bowl?”  Given that I lived in Seattle for 13 years, and witnessed his Steelers literally “steel” a Super Bowl from Seattle via lopsided referee calls, I decided that we should look at what should have been the Seahawks’ championship season:  2005.

image

[Pct Successful Plays] is a measure that I’ve been developing with Hugh Millen.  I’m not going to reveal the “secret sauce” behind said measure, but you can see that in Week 21, when the Seahawks played Pittsburgh in the title game, only 31.2% of their plays were successful – well under their 38.1% total for the year, and their 6th-worst percentage of the year.

Applying Different Formulas in Different Circumstances

Now let’s say that I want to return a different value for this measure in Week 21, which is Super Bowl week.  You know…  I want to “correct” for bad referee calls.

I’ll create a new measure, [Corrected Pct Successful Plays].  In normal cases, I want that measure to just return the same value as would be returned by the original [Pct Successful Plays] measure.

But in week 21, I want to double it.  Just to set things straight.  (In real business, there are many legitimate examples of this technique, like applying a different formula in the West region versus the East region of a sales territory).

If I just use IF() by itself, I will get the error I showed in the previous section.

But if I nest VALUES() inside of the IF(), it will work!

      IF(VALUES(Schedule[WeekNbr])=21, [Pct Successful Plays]* 2,
       [Pct Successful Plays] )

image

Neat, huh?  Returns the same value as [Pct Successful Plays], except it doubles in Week 21.

A Return to the Golden Rules of DAX Measures:  No Naked Columns!

So why is VALUES() required?  Because you cannot have “naked” columns in your measures.  This is one of the “golden rules” for DAX measures that I first introduced over a year ago – see this video for an explanation.

If you’re not interested in watching that video right now, fine, just take my word for it:  in most places, you cannot just include column references in your measures, you have to wrap them in a valid function.  (And go watch the video later, as it’s a concise explanation of the fundamentals of DAX measures, and something I cover on every consulting/training engagement).

VALUES(Table[Column]), however, IS legal in a measure, and VALUES returns the list of values for the specified column in the current context.  So in the last row of the pivot above, it returns 21, and the formula becomes IF(21=21, 2 * [Pct Successful Plays], [Pct Successful Plays]).

Make sense?  OK, good, because I am lying to you.  There’s one more trick I have to show you, as the formula above actually STILL doesn’t work.

But…  IF(VALUES()) only works when there is only a single value!

OK, here’s the formula from above, repeated here:

      IF(VALUES(Schedule[WeekNbr])=21, [Pct Successful Plays] * 2,
       [Pct Successful Plays])

On each individual row of the pivot above, [WeekNbr] DOES have a single value (1, 2, 3, …  21).

There are actually many cases, however, where [WeekNbr] does NOT have a single value.

For instance, in the Grand Total cell of the pivot:

image

In the grand total cell, [WeekNbr] is NOT a single value.  It is actually ALL weeks.  In that case, the VALUES function returns a full column of values, and comparing a whole column to a single value doesn’t work out too well.

I like to visualize that problem in my head:

IF(VALUES(Column)) yields an error for pivot cells where there is more than one value of Column

      IF(VALUES(Column)) yields an error when there is more than one value of Column

And by the way, that’s not an error that you will just see displayed in the pivot’s grand total cell.  It will “tank” the evaluation of the entire pivot:

MDXScript(Sandbox) A table of multiple values was supplied where a single value was expected

Protecting against multi-value situations

Protecting against this is pretty simple.  You just use another IF() to “guard” your IF(VALUES()).

The “guard” if is highlighted below, wrapped around the original formula in normal font.

  =IF(COUNTROWS(VALUES(Schedule[WeekNbr]))=1,
        IF(VALUES(Schedule[WeekNbr])=21, [Pct Successful Plays] * 2,
         [Pct Successful Plays]), 
   [Pct Successful Plays])

In essence, you never let your IF(VALUES()) get evaluated unless there is only one value!  If there is more than one value (as there is in the grand total, or in a subtotal), the formula above just returns the original measure (that’s the “[Pct Successful Plays]” at the end).

Making it simple (seriously, just follow the pattern!)

A lot to digest?

It may seem bad, yes.  But you don’t actually have to grasp it fully.  You can just treat this as a “pattern” that you use.

For example, here is the formula turned into a pattern.  You just substitute your columns and values in the highlighted spots:

  =IF(COUNTROWS(VALUES( <Your Column Here> ))=1,
        IF(VALUES( <Your Column Here> ) =  <Test Value Here> ,
         <Result if True> ,
         <Result if False> ),
   <Result for subtotals and grandtotals> )

The stage is set for some serious fun!

OK, with all of that covered, that sets us up for a series of quick, simple, and powerful techniques that I can share in the next blog post.

 


Buying a PowerPivot Server? Talk to Me First!

March 2, 2011

PowerPivot Servers - A Joint Collaboration Between Pivotstream and um... a leading technology partner :) PowerPivot *IS* Fast… but takes some tuning

Most of us have seen the demos of 100 million rows in PowerPivot, and slicer clicks taking well under a second against those sources.  Super slick.

And whenever I first load a large data set like that and start working with it, I do indeed experience sub-second response times.  But once I go and build sophisticated measures, and put, say, 5-6 slicers on the report, things start slowing down, sometimes by a lot.

When you think about everything PowerPivot is DOING in those cases, it’s staggering.  But the report consumers don’t care – they want speed, not explanations.

So at Pivotstream, we spend as much effort tuning our models and reports for speed as we do creating them in the first place.  We’ve gotten much better at that over time, so it’s almost second nature to us now.

Multiple Times Faster.  AND More Cost Effective.

The quest for speed didn’t end with our modeling and reporting techniques though.  Remember, we’ve been at this for over a year now, and eventually we started to brainstorm and experiment on hardware platforms.  The results have been surprising – in a very good way.

Being a relatively small company, we needed help in this quest, so we approached a leading technology provider for assistance.  We weren’t sure what sort of response to expect – would they understand / take it seriously / appreciate the opportunity?  And even if so…  would our collaborative investigation yield results?

Yes, yes, yes, and BIG YES.

As a technology professional, this has been one of the most stimulating experiences of my entire career.  Real science fiction, cutting edge experimentation…  which is why for now, I’m going to refer to our partner as Cyberdyne.  (This is all so fresh that there are still some legal details to tidy up before I can disclose their true identity).

Anyway, bottom line:  what we’ve developed is both multiple times faster than off-the-shelf server hardware…  AND at the same time, almost certainly more cost effective.

Take the PowerPivot Pepsi ChallengeOur Version of the Pepsi Challenge :)

I’m quite confident that our Black Box (as we are calling it today) will blow the doors off of literally ANYTHING you can get your hands on through any other channel.

So, before you sink big money into PowerPivot server hardware, talk to us.  There’s a good chance that we can save you a lot of time and money.

If you are somewhere in that process today, from early evaluation to the final stages, drop us a note – info@pivotstream.com