I'd appreciate any pointers on this, I need to look up in PP a value based on a range in another PP Table.
I want to return 'BAND' based on where Revenue in the first table falls between High and Low Band Values in the Band Table.
=LOOKUPVALUE(Band[Band],Band[Low],>=[Revenue],Band[High],<=[Revenue])
The Band Table is set up as
Band 0-100 Low 0 High 100
Band 101-200 Low 101 High 200
etc
I've also tried this...
=FILTER(Band[Band],[Revenue]>=Band[Low],[Revenue]<=Band[High])
Thanks for your help.
Gav
LookupValue doesn't support conditional evaluations, instead you can use a FILTER function and FIRSTNONBLANK function to get the right Band[Band].
Create a calculated column in the Combined table using this expression:
LookupBand =
CALCULATE (
FIRSTNONBLANK ( Band[Band], 0 ),
FILTER (
Band,
[Low] <= EARLIER ( Combined[Revenue] )
&& [High] >= EARLIER ( Combined[Revenue] )
)
)
Related
I have a DAX formula that is performing really bad and hopefully someone here can suggest a solution.
I have a table that contains about 400000 rows of data. ProductID's (example field), startdate, enddate and an IsActive flag field. The data out of this table should be reported in several ways. In some reports I want to see all of the active products within a selected period of time and in other reports, I only want to see the number of products that were active on the last day of the month.
So, I have created two DAX queries to calculate this.
First I calculate the active products:
_Calc_Count Fields :=
CALCULATE (
DISTINCTCOUNT ( MyFactTable[ProductID] ),
FILTER (
MyFactTable,
MyFactTable[StartDate] <= CALCULATE ( MAX ( 'Date'[Date] ) )
&& MyFactTable[EndDate] >= CALCULATE ( MIN ( 'Date'[Date] ) )
),
MyFactTable[IsActive] = 1
)
Please be aware of the fact that the report this calculation is used in can also contain a date range (even a whole year (or multiple years) can be selected with a startdate and enddate selected in the filter). The report also slices on other filters like Client Group.
Then I have a second calculation that uses the first one and applies the LASTNONBLANK function:
Last Non Blank Value :=
CALCULATE (
[_Calc_Count Fields],
LASTNONBLANK ( 'Date'[Date], [_Calc_Count Fields] )
)
Both calculations are very, very slow.
Can anyone suggest a better approach? Can the DAX formula be optimized or should it completely be rewritten?
ps. I am using Analysis Services Tabular Model.
Thank you all in advance for your responses!
there are many points to consider for optimizing.
First of all, you need to understand where is the bottleneck.
I would do three separate preliminary tests:
A) change the DISTINCTCOUNT with a simple COUNT
B) Remove the FILTER
C) Remove the IsActive
Then you can understand where to prioritize your effort, however there are some very simple general optimization you can do anyway:
1.Make use of variables, therefore the formula becomes:
_Calc_Count Fields 3:=
VAR _startdate = CALCULATE ( MAX ( 'Date'[Date] ) )
VAR _enddate = CALCULATE ( MIN ( 'Date'[Date] ) )
RETURN
CALCULATE (
DISTINCTCOUNT ( MyFactTable[ProductID] ),
FILTER (
MyFactTable,
MyFactTable[StartDate] <= _startdate
&& MyFactTable[EndDate] >= _enddate
),
MyFactTable[IsActive] = 1
)
2.If you use as first parameter of FILTER an entire Fact Table, Storage Engine will load in memory the Expanded Table which is very expensive. Therefore, as a second step the formula should become:
_Calc_Count Fields 2:=
VAR _startdate = CALCULATE ( MAX ( 'Date'[Date] ) )
VAR _enddate = CALCULATE ( MIN ( 'Date'[Date] ) )
RETURN
CALCULATE (
DISTINCTCOUNT ( MyFactTable[ProductID] ),
MyFactTable[StartDate] <= _startdate && MyFactTable[EndDate] >= _enddate,
MyFactTable[IsActive] = 1
)
Next, based on the preliminary test you can decide where to invest your effort.
The issue is the DISTINCTCOUNT:
- explore some alternative algorithms for approximating DISTINCTCOUNT (HIGH EFFORT)
- try to sort in the data source (back-end) the table by ProductId to allow better compression in AAS
- make sure ProductId is a Integer Data type with Encoding Hint: Value
The issue is in the FILTER:
- Try to change the "&&" with "," (LOW EFFORT)
- Investigate the cardinality of StartDate and EndDate. If they are DateTime, remove the Time part. (LOW EFFORT)
- Try to change the datasource in the back-end and sort by useful fields (for example, StartDate asc, so when AAS will read the table might perform better compression (LOW EFFORT)
- Make sure StartDate and Date are Whole Number data types, with Encoding Hint: Value (LOW EFFORT)
Overview of the table in question
I need to get a distinct count of the column Fkey_Dim_Resource_ID that has holiday to spare.
My Table consists of five columns:
Resource_Allocated_Holiday_ID (Primary Key)
Fkey_Dim_Resource_ID
Fkey_Dim_HolidayYear_ID
Fkey_Dim_Company_ID
Allocated_Holiday_Hrs_Qty
Measure:
Allocated Holiday (Hrs):= Var X= SUM([Allocated_Holiday_Hrs_Qty])
Return if(X =0; BLANK();X)
This measure below then uses the above, and the holiday spent from another metric:
Remaining Holiday (Hrs):= Var X = 'HolidayEntry Numbers'[Allocated Holiday (Hrs)] - [#Holiday Hours]
Return if(X=0;BLANK();X)
And now, I would like a metric that gives me the distinct count of Fkey_Dim_ResourceID where 'Remaining Holiday (hrs)' >0.
I have tried a lot of different stuff, but cannot seem to get it right.
test:=
ADDCOLUMNS(
SUMMARIZE('HolidayEntry Numbers'
;'HolidayEntry Numbers'[Fkey_Dim_Company_ID]
;'HolidayEntry Numbers'[Fkey_Dim_Resource_ID];
'HolidayEntry Numbers'[Fkey_Dim_HolidayYear_Id]
)
;"RemainingHoliday"; sum( [Remaining Holiday (Hrs)])
)
I would like for a distinct count of Fkey_Dim_Resource_ID that has holiday left, that takes into account the context.
Thanks in advance.
With this measure:
test4 virker når ressourcen er med:=COUNTROWS (
FILTER (
ADDCOLUMNS (
VALUES ( 'HolidayEntry
Numbers'[Fkey_Dim_Resource_ID]);
"remholiday"; CALCULATE ( [Remaining Holiday
(Hrs)] )
);
[remholiday] > 0
)
)
I get the following result:
Result of the advice1
So the metric works, when in the context of a Resource, but not when in the context of a Fkey_dim_holiday_Year_ID.
Thanks ion advance.
Resources with remaining holiday hours =
COUNTROWS ( // counts rows in a table
FILTER ( // returns a table, filtering based on predicate
// below is unique values of the column in context, as a
// one-column table
VALUES ( 'HolidayEntry Numbers'[Fkey_Dim_Resource_ID] ),
[Remaining Holiday (hrs)] > 0 // keep rows meeting this criterion
)
)
As a matter of style, you should fully qualify column names as 'Table'[Column], and never fully qualify measure references, i.e. don't prefix with table name. This conforms with all style guides I know, and helps to ensure your code is unambiguous (since both columns and measures are referenced in square brackets).
I need to be able to sum availability based on product and say show me top 3, and categorize the rest as Others. I have two tables in a matrix connected by a product table.
I tried so many ways -
i was able to create this measure for July (which is what i will be sorting with) - I get the correct ranking column for July.
i know i'm missing something. i tried to take that ranking measure statement and add an if statement and couldn't get it to do the ranking.
the picture would make more sense *(my formulas are based on actual column names)
Partner Ranking =
VAR summry =
SUMMARIZE (
ALLSELECTED ( Latest ),
[partner_group],
"Sum", COUNT ( Latest[site_url] )
)
VAR tmp =
ADDCOLUMNS ( summry, "RNK", RANKX ( summry, [Sum],, DESC, DENSE ) )
RETURN
MAXX (
FILTER ( tmp, [partner_group] = SELECTEDVALUE ( Latest[partner_group] ) ),
[RNK]
)
I don't know what to do next. how can i do this when i have a separate table that is the product name that links the two tables?
What if we need to aggregate (Sum) of a value group by two attributes in DAX. I wrote the following measure with Summarize function but it is very slow.
Reorder :=
SUMX (
SUMMARIZE (
TableA,
TableA[ProdID],
TableA[CustID],
"ReordersCount",
VAR VarInvoiceCount =
SUM ( TableA[InvoiceCount] )
RETURN
IF ( VarInvoiceCount > 0, VarInvoiceCount - 1, 0 )
),
[ReordersCount]
)
I also looked for SummarizeColumns but its not working in the report when I am applying other attributes slicers. May be I am missing something?
Looking for optimized solution. Many thanks in advance.
Consider the following approach:
First, create a measure for total number of invoices:
Total Invoice Count = SUM(TableA[InvoiceCount])
Second, create a measure to count a number of first-time invoices, which is simply a number of unique product-customer combinations in your table:
First Invoice Count =
COUNTROWS ( SUMMARIZE ( TableA, TableA[CustID], TableA[ProdID] ) )
Finally, the desired result is simply the difference of these two measures:
Reorder Count = [Total Invoice Count] - [First Invoice Count]
The formula will respond properly to all slicers and filters, and should be very fast because there are no nested iteration loops such as SUMX(SUMMARIZE()), no context transitions and no call-backs inside the loops caused by using IF statements (that's a bit of an advanced topic).
Of course, you can put everything in one measure using variables:
Reorder Count =
VAR Total_Invoice_Count = SUM(TableA[InvoiceCount])
VAR First_Invoice_Count = COUNTROWS ( SUMMARIZE ( TableA, TableA[CustID], TableA[ProdID] ) )
VAR Reorder_Count = Total_Invoice_Count - First_Invoice_Count
RETURN Reorder_Count
although personally I prefer to break measures down because individual measures are easier to understand and debug, and they might have their own use.
The above approach is very efficient, but it assumes that TableA contains only valid orders. If it also has cancellations, returns, etc., that might have zero or negative Invoice counts, then you will have to use a less efficient approach, such as:
Reorder Count =
SUMX (
SUMMARIZE ( TableA, TableA[CustID], TableA[ProdID] ),
VAR Reorder_Count = CALCULATE ( SUM ( TableA[Invoice] ) ) - 1
RETURN
IF ( Reorder_Count > 0, Reorder_Count, 0 )
)
or:
Reorder Count =
SUMX (
SUMMARIZE ( TableA, TableA[CustID], TableA[ProdID] ),
MAX(CALCULATE ( SUM ( TableA[Invoice] ) ) - 1, 0) )
Nevertheless, they should be still faster than your original formula.
I am analysing product distribution data.
We want a snapshot measurement of market penetration [Depth].
Depth := DIVIDE (
[Count of ranged product/store distribution points],
[Count of audited product/store distribution points]
)
I have 2 tables:
'Distribution' (audited distribution points); and
'Calendar' (a date table).
They are related in the model.
For a snapshot at 30 June 2015, I don't want to include new product/stores from November 15, but I do want include any data points that were audited in the prior 3 months.
Logically the numerator is a filtered subset of the denominator so I need the denominator first, which is where I am stuck.
If I just do a basic distinctcount without any fancy code I get this.
Month, Denominator
Mar-15, 1
Apr-15, 0
May-15, 0
Jun-15, 2
Jul-15, 6
Aug-15, 5
Sep-15, 1
Oct-15, 40
Nov-15, 53
Dec-15, 92
But I want something that looks like this:
Month, Denominator
Mar-15, 150
Apr-15, 150
May-15, 150
Jun-15, 170 -- add 1 new product in 20 stores
Jul-15, 170
Aug-15, 170
Sep-15, 170
Oct-15, 200 -- add 1 New product in 30 stores
Nov-15, 200
Dec-15, 200
I need to drop the filter context on Distribution[Date] and apply a filter on Distribution of Distribution[Date] <= Calendar[Date] and then do the distinct count but I get errors.
Count of audited product/store distribution points:=
CALCULATE(
COUNTROWS (
VALUES ( Distribution[ProductStoreKey])
),
NOT ( Distribution[Status On Exit] = "Ineligible" ),
FILTER (
ALL ( Distribution[Date] ),
Distribution[Date] <= Calendar[Date]
)
)
ERROR:
The value for column 'Date' in table 'Distribution' cannot be determined in
the current context. Check that all columns referenced in the calculation
expression exist, and that there are no circular dependencies. This can also
occur when the formula for a measure refers directly to a column without
performing any aggregation--such as sum, average, or count--on that column.
The column does not have a single value; it has many values, one for each
row of the table, and no row has been specified.
It might be a error-proofing of the filter using HASONEVAUE. I'm not sure.
Among other ideas, I've tried rewriting the filter but this doesn't work either.
FILTER (
Distribution,
Distribution[Date] <=
CALCULATE (
MAX(Distribution[Date]),
Distribution[Date]<=Calendar[Date]
)
)
Error:
The expression contains multiple columns, but only a single column can be
used in a True/False expression that is used as a table filter expression.
This code gets the DistibutionDate of the last datapoint at variable Calendar[Date] but I cant figure out how to incorporate it.
Last Ever Dist Date:=
CALCULATE (
LASTDATE( Distribution[DATE] ),
DATESBETWEEN(
Calendar[date],
BLANK(),
LASTDATE(Calendar[Date])
),
ALL(Calendar)
)
How about:
Count of audited product/store distribution points:=
CALCULATE(
DISTINCTCOUNT(Distribution[ProductStoreKey]),
DATESBETWEEN(
Calendar[date],
BLANK(),
LASTDATE(Calendar[Date])
),
ALL(Calendar)
)