I need to divide my calculations into three groups:
- which applied to base cells only (leaves)
- which applied to all cells
- which applied to consolidating cells only (cells of upper hierarchy levels)
For example, I have hierarchy: Year-Quarter-Month.
Base cells of this hierarchy in the "Month" and consolidating cells in a "Year" and "Quarter".
For base cells I can write this "scope":
SCOPE (
[Measures].[Value] ,
[DimProducts].[Name].[Donut] ,
[DimTime].[Month].CHILDREN // month only
);
THIS = [Measures].[Value]*2+100500;
END SCOPE;
And I don't know how to write the "scope" for consolidating cells? I can't to create a "scope" for each hierarchy level such as:
SCOPE (
[Measures].[Value] ,
[DimProducts].[Name].[Donut] ,
[DimTime].[Quarter].CHILDREN // quarter only
);
...
END SCOPE;
SCOPE (
[Measures].[Value] ,
[DimProducts].[Name].[Donut] ,
[DimTime].[Year].CHILDREN // year only
);
...
END SCOPE;
Because there are many dimensions and hierarchy levels and calculations must be applied to all of them.
Maybe there is a simply way for my problem?
You can use MDX functions in SCOPE's subcube expression.
Supposing your Year-Quarter-Month user hierarchy has Year, Quarter and Month levels, you can use the following expression to address levels above the Month level.
SCOPE ( [Measures].[Value]
, [DimProducts].[Name].[Donut]
, Descendants( [DimTime].[Year-Quarter-Month].[All]
, [DimTime].[Year-Quarter-Month].[Quarter]
, SELF_AND_BEFORE
)
);
...
END SCOPE;
Reference:
Descendants MDX function
SCOPE MDX statement
Related
I have the following DAX-formula to retrieve the opening and closing balance for a list of products.
=CALCULATE(MAX(transactions[Balance]);
FILTER(transactions;
transactions[ID] = MAX(transactions[ID])
)
)
This works on row level in my Pivot but when I group this och Product category level I only get one value and not the sum of all the product rows.
My data contains of rows for each transaction and each row have a columns with current balance.
How do I sum each row to get the group sum for the above category "00-01" 26784 and 283500?
One way to do this is to leverage an iterative function like a SUMX.
Assuming that your EndValue is the measure that you defined.
SUMX_Example := SUMX( VALUES ( transactions[ID] ) , [EndValue] )
Which will do the following:
Though VALUES ( transactions[ID] ) it will generate a list of your IDs
For each ID it will run your already created [EndValue] measure
Sum the result of each ID's end value
This is of course assuming [ID] does not cover categories. If ID does cross categories, then you would first do a SUMX using category, with another SUMX that does ID
I have a situation where I kind of need a many-to-many join - which I know isn't possible.
I have one fact table and two dimension tables.
The fact table contains account numbers (as in GL accounts) and amounts. Plus a date field, so the account numbers are not unique.
The first dimension table has just one column listing the reports that can be created by combining the accounts in different ways.
The second dimension table could be called a "roll-up" table. It has 3 columns: report, account, and a line item description field. The latter defines which line on the respective report that the account should be mapped to.
So I want to have a pivot table that has the line item description in the row area and the amount in the values area. With a mechanism for the user to specify which report they want to view. But the join on the account field between the roll-up table and the fact table is many-to-many. If the roll-up table were somehow filtered based on the specific report that the user has selected, THEN it would become one-to-many. Hence the "dynamic" joins in my title.
I've been trying to come up with a connecting table of some kind, but without any luck so far. If anybody has any suggestions/pointers, that would be much appreciated.
I figured out a way to do it using a DAX formula that calculates the field to be placed in the Values area. It uses FILTER and CROSSJOIN combinations to effect the dynamic joins. Note that in order to use a CROSSJOIN I added prefix letters to a couple of the field names (to make them unique). Also, I made it that the Report table (the first dimension table I described) has only one row - containing the report that the user wishes to view.
The DAX formula is as follows:
SUMX (
FILTER (
CROSSJOIN (
fBalances,
FILTER (
CROSSJOIN (
dRollUp,
dReport
), dRollup[Report] = dReport[uReport]
)
), fBalances[fAccount] = dRollUp[Account]
), fBalances[Amount]
)
Subsequent update: I moved it into Power BI where I added a parameter (called myReport) for the user to specify the report. Consequently I deleted the dReport table.
So the Power BI DAX formula becomes:
SUMX (
FILTER (
CROSSJOIN (
fBalances,
FILTER (
CROSSJOIN (
dRollUp,
myReport
), dRollup[Report] = FIRSTNONBLANK ( myReport[myReport], TRUE() )
)
), fBalances[fAccount] = dRollUp[Account]
), fBalances[Amount]
)
I have the following data source:
My pivot rows are Team => Project Name with "Value" column in the Values. I am calculating the % ration of all projects that have value "True" compared to all projects that have a value (disregarding those without values). Here's the formula I use in PowerPivot:
=CALCULATE(COUNTROWS(),'Table'[Value]=TRUE()) / CALCULATE(COUNTROWS(), ('Table'[Value]=FALSE() || 'Table'[Value]=TRUE()), ISLOGICAL('Table'[Value]))
The formula works, however I only need to see this percentage on the "Team" level, the expanded projects should still have "True/False" values. Is this possible? Preferably, without VBA.
Format your code. If you like reading very long lines, that's fine, but use DAX Formatter for the rest of us.
True vs All =
CALCULATE(
COUNTROWS( 'Table' ) // It's considered a best practice
// to explicitly name the table in
// COUNTROWS()
,'Table'[Value]=TRUE()
) / CALCULATE(
COUNTROWS( 'Table' )
// You can remove the test for [Value] = TRUE() ||
// [Value] = FALSE()
,ISLOGICAL('Table'[Value])
)
ConditionalDisplay =
IF(
ISFILTERED( 'Table'[Project] )
&& HASONEVALUE( 'Table'[Project] )
,VALUES( 'Table'[Value] )
,[True vs All]
)
[True vs All] is a cleaned up version of your existing measure.
[ConditionalDisplay] does what its name says. Displays a different value based on conditions.
We check for ISFILTERED() to cover the edge case where a given value of [Team] has only a single project. We check for HASONEVALUE() to cover the case where an explicit filter (slicer or filter) exists on [Project], but more than one is in context (grand total level).
When the two are true, we return VALUES( 'Table'[Value] ), the column made up of the distinct values in [Value]. This is only evaluated when we already know there's exactly one distinct value. A 1x1 table is implicitly converted to scalar in DAX.
When there's more than one distinct value of [Value] or it's not filtered, then we return your original measure.
[ConditionalDisplay] will fail if you have two rows for the same value of [Project] with multiple values of [Value].
I have a requirement in Power Pivot where I need to show value based on the Dimension Column value.
If value is Selling Price then Amount Value of Selling Price from Table1 should display, if Cost Price then Cost Price Amount Should display, if it is Profit the ((SellingPrice-CostPrice)/SellingPrice) should display
My Table Structure is
Table1:-
Table2:-
Required Output:-
If tried the below option:-
1. Calculated Measure:=If(Table[Category]="CostPrice",[CostValue],If(Table1[category]="SellingPrice",[SalesValue],([SalesValue]-[CostValue]/[SalesValue])))
*[CostValue]:=Calculate(Sum(Table1[Amount]),Table1[Category]="CostPrice")
*[Sales Value]:=Calculate(Sum(Table1[Amount]),Table1[Category]="SellingPrice")
Tried this in both Calculated Column and Measure but not giving me required output.
Cost:=
CALCULATE(
SUM( Table1[Amount] )
,Table1[Category] = "CostPrice"
)
Selling:=
CALCULATE(
SUM( Table1[Amount] )
,Table1[Category] = "SellingPrice"
)
Profit:=
DIVIDE(
[Selling] - [Cost]
,[Selling]
)
ConditionalMeasure:=
IF(
HASONEFILTER( Table2[Category] )
,SWITCH(
VALUES( Table2[Category] )
,"CostPrice"
,[Cost]
,"SellingPrice"
,[Selling]
,"Profit"
,[Profit]
)
,[Profit]
)
HASONEFILTER() checks that there is filter context on the named field and that the filter context includes only a single distinct value.
This is just a guard to allow our SWITCH() to refer to VALUES( Table2[Category] ). VALUES() returns a table of all distinct values in the named column or table. So, a 1x1 table can be implicitly converted to a scalar, which we need in SWITCH().
SWITCH() is a case statement.
Our else condition in the IF() is just returning [Profit]. You might want something else, but it's unclear what should happen at the grand total level. You can leave this off, and the measure will be blank in IF()'s else condition.
I was thinking about this a little. I'm not sure why you have your categories on rows. Usually the data set would have columns like: item | CostPrice | SellingPrice | Profit. Then you can just use the columns to define your fields. The model becomes easier and more maintainable.
I have a PowerPivot Data Model in Excel 2013. There are several measures that I have grouped into a named set using MDX - something like this:
{[Measures].[Sum of Value1],
[Measures].[Sum of Value2],
[Measures].[Sum of Value3]}
By using this named Set, I can place multiple measures on the rows or columns of an Excel PivotTable in a single action. My question is, is there any way using MDX (or DAX in the PowerPivot screen when working with the individual measures) to filter out or hide the entire set based on a single measure value (whether that measure is included in the set or not)? Preferably, I'm looking for a way to do this without including another member in the set (I.e. Not a measure).
Ror example, if the Sum of Value3 in the above example was zero, I'd want the entire set to be hidden from the pivot table.
I know I could edit the DAX in the Data Model to return BLANK() for each measure included in the set based on the value of another measure, but there may be times I want to show those measures in all cases. This would require writing at least 2 measures for every one I have now which I don't like the thought of doing.
UPDATE:
Sourav's answer looks great, but unfortunately won't work in my particular scenario, I believe, because I'm using the "Create Set using MDX" function (under the Manage Sets option in the Fields, Items, & Sets ribbon menu) within Excel. It will only let me write the MDX as:
IIF([Measures].[Sum of Value3]=0,
{},
{[Measures].[Sum of Value1],[Measures].[Sum of Value2],[Measures].[Sum of Value3]})
And once I add that new set to the PivotTable, it will still display all 3 measures for any members where [Sum of Value3] is 0.
I think I'm going to have to find an approach using DAX and the Excel Data Model measures.
UPDATE 2:
Below is a screenshot to help illustrate. Keep in mind the data source in my example is not an external cube, it's simply an Excel file linked in the Data Model against which MDX queries (with limitations?) can be run. In this example, I would like the set to return only Rows A and C because Sum of Value3 is not zero. However, as you can see, all rows are being returned. Thanks!
You can't choose to hide/unhide members/sets on the fly. Instead, you can use IIF to conditionally return an empty set
WITH SET MyNamedSet AS
IIF([Measures].[Sum of Value3] = 0,
{},
{[Measures].[Sum of Value1],[Measures].[Sum of Value2], [Measures].[Sum of Value3]}
Working example in AdventureWorks for #whytheq(DISCLAIMER - Cube was created by me for testing purposes)
with set abc as
iif([Measures].[Fact Internet Sales Count]>34229,
{
[Measures].[Fact Internet Sales Count],
[Measures].[Extended Amount - Fact Internet Sales]
},
{}
)
SELECT
abc
on 0
from [AdventureWorksDW]
where [Due Date].[Year].&[2004]
As you can see, the scope IS changing the results.
An alternative would be to create a dummy measure that returns null or 1 depending on your [Measures].[Sum of Value3]. Then multiply all other target measures by this dummy measure.
Here is an example of you scenario in AdvWrks:
SELECT
[Product].[Product Categories].[Category].[Components] ON 0
,{
[Measures].[Internet Sales Amount]
,[Measures].[Sales Amount]
,[Measures].[Standard Product Cost]
,[Measures].[Total Product Cost]
} ON 1
FROM [Adventure Works];
Returns this:
Adding the dummy measure and amending the other measures:
WITH
MEMBER [Measures].[isItZero] AS
IIF
(
[Measures].[Internet Sales Amount] = 0
,null
,1
)
MEMBER [Measures].[Sales Amount NEW] AS
[Measures].[Sales Amount] * [Measures].[isItZero]
MEMBER [Measures].[Standard Product Cost NEW] AS
[Measures].[Standard Product Cost] * [Measures].[isItZero]
MEMBER [Measures].[Total Product Cost NEW] AS
[Measures].[Total Product Cost] * [Measures].[isItZero]
SELECT
NON EMPTY //<<<<this is required
{
[Measures].[Internet Sales Amount]
,[Measures].[Sales Amount NEW]
,[Measures].[Standard Product Cost NEW]
,[Measures].[Total Product Cost NEW]
} ON 0
,{} ON 1
FROM [Adventure Works]
WHERE
[Product].[Product Categories].[Category].[Components];
Now this returns:
EDIT
According to your latest edit please just try this (I'm assuming you're using Excel 2013):
Create two new measures to replace two of the existing ones:
Name: "Sum of Value1 NEW"
Definition:
IIF
(
[Measures].[Sum of Value3] = 0
,null
,[Measures].[Sum of Value1]
)
Name: "Sum of Value2 NEW"
Definition:
IIF
(
[Measures].[Sum of Value3] = 0
,null
,[Measures].[Sum of Value2]
)
Now use only these three measures in your pivot and just use the ID dimension in a normal way on rows i.e. do not use the custom set you have already tried.
[Measures].[Sum of Value1 NEW]
[Measures].[Sum of Value2 NEW]
[Measures].[Sum of Value3]
Has ID B should now disappear?