DAX Measure with different granularities - powerpivot

I'm looking for help with how to write a specific DAX measure. Here is a simplified version of my data and model:
Tables:
Model:
Measures:
Total Amt:=SUM(Amounts[Amt])
Total Pos Amt:=SUMX(Amounts, IF([Amt]<0,0,[Amt]))
Total Amt All:=CALCULATE([Total Pos Amt],ALL(Ptr))
Total Amt All 2:=SUMX(Bridge,CALCULATE([Total Pos Amt],ALL(Ptr)))
Total Amt All 3:=SUMX(VALUES(Bridge[Pri]),CALCULATE([Total Pos Amt],ALL(Ptr)))
As you can see in the first PivotTable (where [Pri] & [Ptr] are row fields), the highlighted cells show values with an issue. The [Total Pos Amt] measure sums up the [Amt] column in the Amounts table by iterating through it and evaluating an expression where negative amounts are treated as zero and positive amounts are kept. At a [Pri] level granularity, I want that same logic to apply (i.e. evaluate the expression at a [Ptr] level). The problem with the [Total Amt All] measure is that on the PivotTable I get a row for [Ptr] Z under [Pri] A which I don't want. Measures [Total Amt All 2] and [Total Amt All 3] solve that issue but the subtotals at a [Pri] level are wrong in [Total Amt All 2] and the grand total is wrong in [Total Amt All 3].
Any help would be greatly appreciated! How can I write a measure that won't show a [Ptr] that is not associated with a [Pri] per the Bridge table, but that also correctly sums up the [Total Pos Amt] measure at a [Pri] level?

So one of your problems might be which fields you're using in your PivotTable. I got it work by using your bridge table as the fields:
TotalAmtBridged:=CALCULATE ( SUMX(Amounts, IF([Amt]<0,0,[Amt]) ) , Bridge )
FinalTotalAmt:= Calculate([TotalAmtBridged], ALL(Bridge[Ptr])
And then the PivotTable uses Bridge[Pri] and Bridge[Ptr]. So TotalAmtBridged just forces your total amount to use the Bridge context, and then FinalTotal says ignore Ptr (i.e. for each row we're displaying figure out the total amount for Bridge[Pri] only).
And then the grand total's already doing that, so Bob's your uncle.

Related

Scope Statement Alternative to Slow CrossJoin Count MDX

The below MDX works for my purpose but is extremely slow. Is there a scope statement Essentially I want to count the remaining cross joined contact/purchases combinations where the summed amount is $>5000.
The cross product is a total of 290M rows but I am not sure how to structure this differently to improve performance. Thank you for any help.
CREATE HIDDEN STATIC SET [Over 5K Plus Test 2]
AS NONEMPTY (([Contact].[Contact ID].[Contact ID],[Fund Sold].[Fund Sold ID].[Fund Sold ID]),
[Measures].[FA And Team Gross Sales with FAs Including All Vehicles]);
CREATE MEMBER CURRENTCUBE.[Measures].[FA and Team Product Count]
AS COUNT(EXISTING((Filter([Over 5K Plus Test 2], [Measures].[FA And Team Gross Sales with FAs Including All Vehicles] >= 5000)))),
Try this which avoids the Filter:
CREATE MEMBER CURRENTCUBE.[Measures].[FA and Team Product Count]
AS SUM(
Existing [Contact].[Contact ID].[Contact ID].Members
* Existing [Fund Sold].[Fund Sold ID].[Fund Sold ID].Members,
IIF([Measures].[FA And Team Gross Sales with FAs Including All Vehicles] >= 5000, 1, Null)
);
If that is still slow then post the calculation behind FA And Team Gross Sales with FAs Including All Vehicles
The more efficient way to accomplish this requires a bit more effort but will perform better because it avoids the Existing function. First you have to create a column in the DSV which is a calculated column in the fact table using this expression:
CAST(null as int)
Then create a new measure called “FA and Team Product Count” on this column. Expand the column binding and choose NullHandling=Preserve. This has to be a physical measure not a calculated measure because only scoped assignments to physical measures aggregate up.
Then add the following statement to the MDX script (instead of the calculated measure mentioned at the top):
([Measures].[FA and Team Product Count],
[Contact].[Contact ID].[Contact ID].Members,
[Fund Sold].[Fund Sold ID].[Fund Sold ID].Members) =
IIF([Measures].[FA And Team Gross Sales with FAs Including All Vehicles] >= 5000, 1, Null);

Power BI Matrix sum totalling %ages incorrectly

I have a measure in PowerBI that looks like:
Measure 2 = IF(HASONEVALUE('CPP'[KPI Group]),
SUMX('CPP',
DIVIDE(1,'Corporate Planning Project'[Full Year
Budget],0)*'CPP'[Actual Y.T.D]
),
""
)
Basically my matrix looks like:
---- KPI Group ----ActualYTD ----FullYearBudget ----Measure2
A ----$29,666,609 ----$95,540,594 ----1804%
B ---- $2,297,809 ---- $20,153,995 ---- 503%
Once you drilldown into group A, the matrix looks like:
KPI Group ---- ActualYTD---- FullYearBudget---- Measure2
A>
----1415----$1,252,548----$322,180----388.77%
----2223----$821,236----$830,860----98.84%
etc, so you can see that at the drilled down level the Measure2 calculates correctly, it is only at the highest level that the Measure2 is being summed, and so the sum of ALL of the %ages added together comes to 1804%, instead of the measure calculating at that level too, which would sum of fullyear budgets divided by sum of ActualYTD as a percentage.
Can anyone help please?
Thankyou
It seems like the purpose of your Measure2 is to show [Actual Y.T.D] as a percentage of [Full Year Budget], and to only show that if you are in the context of a single [KPI group].
The reason you aren't getting the result you expect is probably because you are using SUMX() where you shouldn't, SUMX() will calculate the percentage once for each row of the 'CPP' table and then add all of those together.
Try the following measure:
Measure 2 =
IF(
HASONEVALUE(CPP[KPI Group]),
DIVIDE(
SUM(CPP[Actual Y.T.D]),
SUM('Corporate Planning Project'[Full Year Budget]),
0
)
)

“Decrease” the measure in OLAP Cube

I have an OLAP Cube in which there is a Parent-Child Account Dimension.
My goal is to set a certain measure value on the GROSS-PROFIT Account , with a certain logic :
GROSS PROFIT = REVENUES - COSTS
GROSS PROFIT is the parent of REVENUES and COSTS in my account hierarchy, and now the measure shows me the sum (obviously) , not the substraction.
The measure is named [Measures].[Report]
I don’t know how to return, in my measure, the substraction only for the GROSS PROFIT Account , so please help me.
Tks a lot
Daniel
I solved the problem , I saw that exists an “operator column” in the dimension definition, that permits to perform some operation like substraction and addition between members only specifying a certain value column (setted for ex to “+” or “-“)

Common calculated measure across all dimensions

I have a cube with 4 dimensions and I have a measure called Transaction Count. Now I want to calculate the Percentage across all the dimensions for that above measure.
I also have a dimension called Cars. I have the count across all the Cars and now I have defined a calculated measure for calculating the Percentage of each car from the total number of transactions. But it will work only for that particular dimension.
How I can create a single percentage calculated measure which can be used across all the dimensions?
MDX for the calculated measure: (which is working for only Carmake dimension)
CASE
WHEN ISEMPTY( [MEASURES].[Trans COUNT] )
THEN 0
ELSE ([Dim Car Make].[Hierarchy].CURRENTMEMBER,
[MEASURES].[FACT COLORPERFORMANCE COUNT])/
( [DIM CAR MAKE].[CARMAKE].[(ALL)].[ALL],
[MEASURES].[Trans COUNT])
END
I already have a Trancount(1000) measure. Now I need to create a calculated measure Freq % which should be calculated across all the dimensions.
Screenshot -> http://i.stack.imgur.com/iuaQO.jpg (need 10 rep for posting images)
Table 1 in screenshot - you drag and drop the carmake dimension, then both Tran Count and Freq% should be calculated as per CarMake breakdown.
Table 2 in screenshot - you remove CarMake and drag Quality, then both Tran Count and Freq% should be calculated as per Quality breakdown.
Table 3 in screenshot - you remove Quality and drag Brand, then both Tran Count and Freq% should be calculated as per brand breakdown.
The best way i found is using AXIS() to dynamically get the currently used dimension.
with
member Member_Lvl as AXIS(0).item(0).level.ordinal --get the level for next calc
member All_Member as sum(ancestor(axis(0).item(0).hierarchy.currentMember,<yourMeasure>),Member_Lvl )
member Percent_of_All as sum(axis(0).item(0).hierarchy.currentMember,<yourMeasure>) / All_Member
select <Your Dim > on 0, {<Your Measure>, Percent_of_All} on 1
from <Your Cueb>
NOTICE: replace the SUM function on the calculations if you need other aggregation.

MDX - Count of Filtered CROSSJOIN - Performance Issues

BACKGROUND: I've been using MDX for a bit but I am by no means an expert at it - looking for some performance help. I'm working on a set of "Number of Stores Authorized / In-Stock / Selling / Etc" calculated measures (MDX) in a SQL Server Analysis Services 2012 Cube. I had these calculations performing well originally, but discovered that they weren't aggregating across my product hierarchy the way I needed them to. The two hierarchies predominantly used in this report are Business -> Item and Division -> Store.
For example, in the original MDX calcs the Stores In-Stock measure would perform correctly at the "Item" level but wouldn't roll up a proper sum to the "Business" level above it. At the business level, we want to see the total number of store/product combinations in-stock, not a distinct or MAX value as it appeared to do originally.
ORIGINAL QUERY RESULTS: Here's an example of it NOT working correctly (imagine this is an Excel Pivot Table):
[FILTER: CURRENT WEEK DAYS]
[BUSINESS] [AUTH. STORES] [STORES IN-STOCK] [% OF STORES IN STOCK]
[+] Business One 2,416 2,392 99.01%
[-] Business Two 2,377 2,108 93.39%
-Item 1 2,242 2,094 99.43%
-Item 2 2,234 1,878 84.06%
-Item 3 2,377 2,108 88.68%
-Item N ... ... ...
FIXED QUERY RESULTS: After much trial and error, I switched to using a filtered count of a CROSSJOIN() of the two hierarchies using the DESCENDANTS() function, which yielded the correct numbers (below):
[FILTER: CURRENT WEEK DAYS]
[BUSINESS] [AUTH. STORES] [STORES IN-STOCK] [% OF STORES IN STOCK]
[+] Business One 215,644 149,301 93.90%
[-] Business Two 86,898 55,532 83.02%
-Item 1 2,242 2,094 99.43%
-Item 2 2,234 1,878 99.31%
-Item 3 2,377 2,108 99.11%
-Item N ... ... ...
QUERY THAT NEEDS HELP: Here is the "new" query that yields the results above:
CREATE MEMBER CURRENTCUBE.[Measures].[Num Stores In-Stock]
AS COUNT(
FILTER(
CROSSJOIN(
DESCENDANTS(
[Product].[Item].CURRENTMEMBER,
[Product].[Item].[UPC]
),
DESCENDANTS(
[Division].[Store].CURRENTMEMBER,
[Division].[Store].[Store ID]
)
),
[Measures].[Inventory Qty] > 0
)
),
FORMAT_STRING = "#,#",
NON_EMPTY_BEHAVIOR = { [Inventory Qty] },
This query syntax is used in a bunch of other "Number of Stores Selling / Out of Stock / Etc."-type calculated measures in the cube, with only a variation to the [Inventory Qty] condition at the bottom or by chaining additional conditions.
In its current condition, this query can take 2-3 minutes to run which is way too long for the audience of this reporting. Can anyone think of a way to reduce the query load or help me rewrite this to be more efficient?
Thank you!
UPDATE 2/24/2014: We solved this issue by bypassing a lot of the MDX involved and adding flag values to our named query in the DSV.
For example, instead of doing a filter command in the MDX code for "number of stores selling" - we simply added this to the fact table named query...
CASE WHEN [Sales Qty] > 0
THEN 1
ELSE NULL
END AS [Flag_Selling]
...then we simply aggregated these measures as LastNonEmpty in the cube. They roll up much faster than the full-on MDX queries.
It should be much faster to model your conditions into the cube, avoiding the slow Filter function:
If there are just a handful of conditions, add an attribute for each of them with two values, one for condition fulfilled, say "cond: yes", and one for condition not fulfilled, say "cond: no". You can define this in a view on the physical fact table, or in the DSV, or you can model it physically. These attributes can be added to the fact table directly, defining a dimension on the same table, or more cleanly as a separate dimension table referenced from the fact table. Then define your measure as
CREATE MEMBER CURRENTCUBE.[Measures].[Num Stores In-Stock]
AS COUNT(
CROSSJOIN(
DESCENDANTS(
[Product].[Item].CURRENTMEMBER,
[Product].[Item].[UPC]
),
DESCENDANTS(
[Division].[Store].CURRENTMEMBER,
[Division].[Store].[Store ID]
),
{ [Flag dim].[cond].[cond: yes] }
)
)
Possibly, you even could define the measure as a standard count measure of the fact table.
In case there are many conditions, it might make sense to add just a single attribute with one value for each condition as a many-to-many relationship. This will be slightly slower, but still faster than the Filter call.
I believe you can avoid the cross join as well as filter completely. Try using this:
CREATE MEMBER CURRENTCUBE.[Measures].[Num Stores In-Stock]
AS
CASE WHEN [Product].[Item Name].CURRENTMEMBER IS [Product].[Item Name].[All]
THEN
SUM(EXISTS([Product].[Item Name].[Item Name].MEMBERS,[Business].[Business Name].CURRENTMEMBER),
COUNT(
EXISTS(
[Division].[Store].[Store].MEMBERS,
(
[Business].[Business Name].CURRENTMEMBER,
[Product].[Item Name].CURRENTMEMBER
),
"Measure Group Name"
)
))
ELSE
COUNT(
EXISTS(
[Division].[Store].[Store].MEMBERS,
(
[Business].[Business Name].CURRENTMEMBER,
[Product].[Item Name].CURRENTMEMBER
),
"Measure Group Name"
)
)
END
I tried it using a dimension in my cube and using Area-Subsidiary hierarchy.
The case statement handles the situation of viewing data at Business level. Basically, the SUM() across all members of Item Names used in CASE statement calculates values for individual Item Names and then sums up all the values. I believe this is what you needed.