In the following Power BI file, I have defined a calculation group 'CG - Last days'[Name] = "5 last days" as follow :
VAR tbl_FILTER =
TOPN(
10
, dim_DATES
, dim_DATES[Date]
, DESC
)
RETURN
CALCULATE(
SELECTEDMEASURE()
, KEEPFILTERS( tbl_FILTER )
)
My problem is it does not produce the expected output :
filtering on the 10 most recent dates of a date table with only January and February should return a count of 10 dates only for the month of February ; but that is not what I get :
If anyone knows why, I am all ears.
One problem here is that calculation items don't modify just any DAX expression, only measure references. Try defining a count measure COUNT( dim_DATES_2[dat_DATE] ) and using that in your test instead.
Please see this article: https://www.sqlbi.com/articles/understanding-calculation-groups/
In particular, this part
The application of a calculation item replaces a measure reference with the expression of the calculation item, still applying an implicit context transition. Focus your attention on this sentence: A measure reference is replaced. Without a measure reference, a calculation item does not apply any modification. For example, the following code is not affected by any calculation item because it does not contain any measure reference:
CALCULATE (
SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ),
'Time Intelligence'[Time calc] = "YTD"
)
Edit: As mentioned in the comments, you also need to use ALL(dim_DATES) instead of dim_Dates inside the TOPN. This is because the dim_Dates has filter context applied to it from the visual, so only includes February dates in the February row and Januari dates in the Januari row. ALL removes this filter context and returns the top dates from the unfiltered dates table.
Related
Below is the sample dataset
The data has two slicers ( date and category ) shown below
I am writing a DAX Statement to multiply the sum(values) * 10 only if the date range is in the current year 2023.
The StartYear gives the start of the current year, firstD gives the lowest date from the date slicer.
Formula =
var new = sum(Test[Value]) * 10
var startyear = DATE(YEAR(TODAY()),1,1)
var firstD = CALCULATE( MIN( Test[Date]), ALLSELECTED(Test[Date]) )
return if( ISFILTERED(Test[Categories]) && firstD >= startyear, new, 0 )
Now when I filter dates to 2023, the total value should be 2300 but it shows as 0
However the DAX works when I select A or B
If we remove the ISFILTERED function then, it gives wrong value, the expected value is 0 because the start date is in 2022, but it shows 650
let me know if that is the right syntax
It looks like you are not using a separate calendar table to handle this, which you need!
In your very last example you have set your slicer to some time late 2022, but the minimum value of 'Test'[Date] for your selected category is in year 2023. Hint: set the slicer to e.g. 2022-12-14, this will include a 2022-date for Category A in your data.
Your measure behaves exactly how it is supposed to, in other words!
To fix this, you need to do the following:
Create a calendar table in your model, this should contain contiguous dates, which is necessary for the filtering method you want
Establish a relationship between the calendar table and existing Test table.
Use the date column from your new calendar table in your slicer and as date reference in your measure
Exactly how to create a calendar table is thoroughly documented on Google, I recommend you search and find an article or video you understand for implementing this.
Lastly: Your use of ISFILTERED in this measure seems strange, since you mention nowhere the requirement of only showing a number if the column you are testing filtering on is filtered, if that makes sense.. :-) The way you describe your calculation, you only need to check whether the selected date range starts in current year.
Create a measure inside the Calculations table which calculates which takes the sum of line price and filters on the product category "Bikes" and YEAR(Sales[OrderDate]) year being 2018.
Name this measure 2018 Bikes Revenue.
the code solution is
2018 Bikes Revenue =
CALCULATE (
SUM ( Sales[LinePrice] ),
Sales[ProductCategory] = "Bikes",
YEAR ( Sales[OrderDate] ) = 2018
)
it shows errors "The expression specified in the query is not a valid table expression."
need help here
Your error message indicates that you are trying to use your DAX formula to create a calculated table. However, the result of your expression is a single number so you can only use it as a calculated measure. Take care to use the proper UI for your formula
My intention is to populate days of the month to simulate a data warehouse periodic snapshot table using DAX measures. My goal is to show non-additive values for the quantity.
Consider the following transactions:
The granularity of my snapshot table is day. So it should show the following:
Take note that a day may have multiple entries but I am only interested in the latest entry for the day. If I am looking at the figures using a week period it should show the latest entry for the week. It all depends on the context fixter.
However after applying the measure I end up with:
There are three transactions. Two on day 2 and the other on day 4. Instead of calculating a running total I want to show the latest Qty for the days which have no transactions without running accumulating totals. So, day 4 should show 4 instead of summing up day 3 and day 4 which gives me 10. I've been experimenting with LASTNONBLANK without much success.
This is the measure I'm using:
Snapshot =
CALCULATE(
SUM('Inventory'[Quantity]),
FILTER(
ALL ( 'Date'[Date] ),
'Date'[Date] <= MAX( 'Date'[Date] )
)
)
There are two tables involved:
Table # 1: Inventory table containing the transactions. It includes the product id, the date/time the transaction was recorded and the quantity.
Table # 2: A date table 'Date' which has been marked as a date table in Power BI. There is a relationship between the Inventory and the Date table based on a date key. So, in the measure, 'Date'[Date] refers to the Date column in the Date table.
You can use the LASTNONBLANKVALUE function, that returns the last value of the expression specified as second parameter sorted by the column specified as first parameter.
Since LASTNONBLANKVALUE implicitly wraps the second parameter into a CALCULATE, a context transition happens and therefore the row context is transformed into the corresponding filter context. So we also need to use VALUES to apply the filter context to the T[Qty] column. The returned table is a single row column and DAX can automatically convert a single column, single row table to a scalar value.
Then, since we don't have a dimension table we have to get rid of cross-filtering, therefore we must use REMOVEFILTERS over the whole table.
the filter expression T[Day] < MaxDay is needed because LASTNONBLANKVALUE must be called in a filter context containing all the rows preceding and including the current one.
So, assuming that the table name is T with fields Day and Qty like in your sample data, this code should work
Edit: changed in order to support multiple rows with same day, assuming the desired result is the sum of the last day quantities
Measure =
VAR MaxDay =
MAX ( T[Day] )
RETURN
CALCULATE (
LASTNONBLANKVALUE (
T[Day],
SUM ( T[Qty] )
),
T[Day] <= MaxDay,
REMOVEFILTERS ( T )
) + 0
Edit: after reading the comments, this might work on your model (untested)
Measure =
VAR MaxDay =
MAX ( 'Date'[Date] )
RETURN
CALCULATE (
LASTNONBLANKVALUE (
Inventory[RecordedDate],
SUM ( Inventory[Quantity] )
),
'Date'[Date] <= MaxDay
) + 0
How to construct DAX measure to calculate sum of YTD value for specific month?
Here we have FactTable grouped by months. FactTable is filled with both Actual data and Forecast data. The only way to know when Actual end is information in table [Cut of date] in column [End of YTD]. In table [Cut of date] in column [End of YTD] – it is a single value table – we have the interesting chosen month, for which we want to see the calculation of YTD. In our case it is March. FactTable is updated irregularly every month with usually one month delay. There is no way of linking it to time functions like TODAY because of irregular update.
We would like to have a correct value of YTD displayed in yellow Card Visual for the month [End of YTD]. When we click on the slicer on "2018-03" we get almost what we want – correct value of 66 in the yellow Card. However this solution is not automatic. I want to see correct value automatically when the [End of YTD] month changes, in our case to April or then to May. I do not want it done by user.
My desperate effort can be downloaded from file: DAX YTD.pbix
I pursued the deer in various ways:
By using FILTER function in DAX measures. But it seems that the
FILTER function is to harsh. It is applied to fact table first,
selecting only one month, and then calculating YTD value wrongly. So if
there would be any option for forcing order of calculation and filtering, there would
be hope.
I tried SWITCH function to display proper result
for specific month and 0 or null for other months. Although I
succeed in this, I was not able to take advantage of it. When it
came to filtering I was as hopeless as before. BTW I would be able
to make it if SWITCH produced totals at the end of the table, but it
does not. Surprisingly.
I put some hopes in RELATED function to display proper results in the [Cut off date] table. I have not walk out of the fog so far.
I would appreciate your help.
Update before bounty.
Going to higher level. I have introduced a Category column to FactTable. Please download DAX YTD by category.pbix. So filtering gets more complex now. I would like to have correct YTD figures for Apples category.
Did you use the Date column from the Calendar table, instead of the one from FactTable?
If you use the date column from FactTable, when you apply a filter on the date, it will filter on the fact records which is in March, and then do the calculation afterwards, hence the result 33.
If you use the one from Calendar, when you apply a filter on it, it filters the records on Calendar (which you want to show in the chart), so the underlying calculation will still remain intact.
A working example:
Calendar = CALENDAR(DATE(2010, 1, 1), DATE(2020, 12, 31))
I suggest you to change the calculations of the measures to avoid missing values in some cases:
Total = SUM(FactTable[Value])
MTD = TOTALMTD([Total], 'Calendar'[Date])
YTD = TOTALYTD([Total], 'Calendar'[Date])
UPDATE:
It's much clearer to me what you want to achieve now but it still seems an XY problem to me.
I understand that you want to show the dashboard as is so that users do not need to click/input every time to see what they are supposed to see. That's why I don't get why you need to create a new table to store the Cut off date (End of YTD). How is it going to be maintained automatically?
The relative date filtering solution above actually still works in the .pbix file you've shared. If you drag the Date column from the Calendar table to visual level filters for the yellow card and add the relative date filtering, it should work as below:
For the End of YTD visual, you can use the following measure to get the first day of last calendar month, so you don't need to create another table for it:
End of YTD = EOMONTH(TODAY(), -2) + 1
And hopefully this is what you want to achieve:
Updated file for your reference.
UPDATE again:
I think you'll have to write your own YTD calculation instead of using the built-in one, so that you can make use of the cut off date you defined in another table. Here I assume that you have one and only one row in 'Cut off date'[End of YTD]. Note that I've added ALL() to the filter, so that the yellow card remains the same (66) instead of showing blank when some other rows/filters are clicked:
YTD_Special =
CALCULATE(
[Total],
FILTER(
ALL(FactTable),
FactTable[Date] >= DATE(YEAR(VALUES('Cut off date'[End of YTD])), 1, 1) &&
FactTable[Date] <= VALUES('Cut off date'[End of YTD])
)
)
I would resolve this by adding a calculated column to your Calendar table to categorise each row into either "YTD" or "Other", e.g.
Is YTD =
IF (
[Date] >= DATE ( YEAR ( DISTINCT ( 'Cut off date'[End of YTD] ) ), 1, 1 )
&& [Date] <= DISTINCT ( 'Cut off date'[End of YTD] ),
"YTD",
"Other"
)
I would then add the new Is YTD field to the Visual level filters of your Card visual, and choose YTD from the Basic filtering list. The measure shown can be your simple Total measure: SUM(FactTable[Value]).
This is a far more flexible and resuable solution than any specific measure gymnastics. You will not need an explosion of measures to apply the required logic on top of every base measure - they will all just work naturally. You can apply the filter at any level: Visual, Page, Report, or put it in a Slicer for control by the end user.
I prefer to return text results e.g. "YTD" / "Other" (rather than 1/0, True/False or Yes/No), as this allows for easy extension to other requirements e.g. "Prior YTD" (1 Jan 2017 to 1 Mar 2017). It also is clearer when used in visuals.
Actually I shouldn't claim the credit for this design - this roughly follows how Cognos Transformer's Relative Time functionality worked back in the 90s.
I did something like this in my Periodic/YTD report (last sheet): http://ciprianbusila.ro/
I have used the index value of the month selected (range 1-12) and based on this I have created a measure using max function please see the code below:
ACT = var
ACT_periodic=calculate([Value],Scenarios[Scenario]=values(Scenarios[Scenario]))
var max_month=max(Periods[Period Order])
var ACT_YTD=CALCULATE([Value],Scenarios[Scenario]=VALUES(Scenarios[Scenario]),all(Periods[Month]),Periods[Period Order]<=max_month)
var myselection=if(HASONEVALUE(MRD_view[.]),values(MRD_view[.]),"PERIODIC")
return
switch(
true(),
myselection="PERIODIC",ACT_periodic,
myselection="YEAR TO DATE",ACT_YTD,
ACT_periodic
)
I have following scenario which has been simplified a little:
Costs fact table:
date, project_key, costs €
Project dimension:
project_key, name, starting date, ending date
Date dimension:
date, years, months, weeks, etc
I would need to create a measure which would tell project duration of days using starting and ending dates from project dimension. The first challenge is that there isn't transactions for all days in the fact table. Project starting date might be 1st of January but first cost transaction is on fact table like 15th on January. So we still need to calculate the days between starting and ending date if on filter context.
So the second challenge is the filter context. User might want to view only February. So it project starting date is 1.6.2016 and ending date is 1.11.2016 and user wants to view only September it should display only 30 days.
The third challenge is to view days for multiple projects. So if user selects only single day it should view count for all of the projects in progress.
I'm thankful for any help which could lead towards the solution. So don't hesitate to ask more details if needed.
edit: Here is a picture to explain this better:
Update 7.2.2017
Still trying to create a single measure for this solution. Measure which user could use with only dates, projects or as it is. Separate calculated column for ongoing project counts per day would be easy solution but it would only filter by date table.
Update 9.2.2017
Thank you all for your efforts. As an end result I'm confident that calculations not based on fact table are quite tricky. For this specific case I ended up doing new table with CROSS JOIN on dates and project ids to fulfill all requirements. One option also was to add starting and ending dates as own lines to fact table with zero costs. The real solution also have more dimensions we need to take into consideration.
To get the expected result you have to create a calculated column and a measure, the calculated column lets count the number of projects in dates where projects were executed and the measure to count the number of days elapsed from [starting_date] and [ending_date] in each project taking in account filters.
The calculated column have to be created in the dim_date table using this expression:
Count of Projects =
SUMX (
FILTER (
project_dim,
[starting_date] <= EARLIER ( date_dim[date] )
&& [ending_date] >= EARLIER ( date_dim[date] )
),
1
)
The measure should be created in the project_dim table using this expression:
Duration (Days) =
DATEDIFF (
MAX ( MIN ( [starting_date] ), MIN ( date_dim[date] ) ),
MIN ( MAX ( [ending_date] ), MAX ( date_dim[date] ) ),
DAY
)
+ 1
The result you will get is something like this:
And this if you filter the week using an slicer or a filter on dim_date table
Update
Support for SSAS 2014 - DATEDIFF() is available in SSAS 2016.
First of all, it is important you realize you are measuring two different things but you want only one measure visible to your users. In the first Expected result you want to get the number of projects running in each date while in the Expected results 2 and 3 (in the OP) you want the days elapsed in each project taking in account filters on date_dim.
You can create a measure to wrap both measures in one and use HASONEFILTER to determine the context where each measure should run. Before continue with the wrapping measure check the below measure that replaces the measure posted above using DATEDIFF function which doesn't work in your environment.
After creating the previous calculated column that is required to determine the number of projects in each date, create a measure called Duration Measure, this measure won't be used by your users but lets us calculate the final measure.
Duration Measure = SUMX(FILTER (
date_dim,
date_dim[date] >= MIN ( project_dim[starting_date] )
&& date_dim[date] <= MAX ( project_dim[ending_date] )
),1
)
Now the final measure which your users should interact can be written like this:
Duration (Days) =
IF (
HASONEFILTER ( date_dim[date] ),
SUM ( date_dim[Count of Projects] ),
[Duration Measure]
)
This measure will determine the context and will return the right measure for the given context. So you can add the same measure for both tables and it will return the desired result.
Despite this solution is demonstrated in Power BI it works in Power Pivot too.
First I would create 2 relationships:
project_dim[project_key] => costs_fact[project_key]
date_dim[date] => costs_fact[date]
The Costs measure would be just: SUM ( costs_fact[costs] )
The Duration (days) measure needs a CALCULATE to change the filter context on the Date dimension. This is effectively calculating a relationship between project_dim and date_dim on the fly, based on the selected rows from both tables.
Duration (days) =
CALCULATE (
COUNTROWS ( date_dim ),
FILTER (
date_dim,
date_dim[date] >= MIN ( project_dim[starting_date] )
&& date_dim[date] <= MAX ( project_dim[ending_date] )
)
)
I suggest you to separate the measure Duration (days) into different calculated column/measure as they don't actually have the same meaning under different contexts.
First of all, create a one-to-many relationship between dates/costs and projects/costs. (Note the single cross filter direction or the filter context will be wrongly applied during calculation)
For the Expected result 1, I've created a calculated column in the date dimension called Project (days). It counts how many projects are in progress for a given day.
Project (days) =
COUNTROWS(
FILTER(
projects,
dates[date] >= projects[starting_date] &&
dates[date] <= projects[ending_date]
)
)
P.S. If you want to have aggregated results on weekly/monthly basis, you can further create a measure and aggregate Project (days).
For Expected result 2 and 3, the measure Duration (days) is as follows:
Duration (days) =
COUNTROWS(
FILTER(
dates,
dates[date] >= FIRSTDATE(projects[starting_date]) &&
dates[date] <= FIRSTDATE(projects[ending_date])
)
)
The result will be as expected: