Create table with summarization and latest value of the year - powerbi

For each ClientNo I want the Type classification corresponding to the last date of each Year:
Thus, the table above should be summarized as:
So, somehow, we need two intermediate tables:
Unique values for years, like VALUES(Table[Date].Year)
Unique values for ClientNo, like VALUES(Table[ClientNo])
Then for each combination of Year and ClientNo, get the latest date for each year and finally get the Type classification.

You should be able to do this in two steps along these lines:
Summary =
VAR MaxDates =
SUMMARIZE (
ADDCOLUMNS ( Table1, "Year", YEAR ( Table1[Date] ) ),
Table1[ClientNo],
[Year],
"MaxDate", MAX ( Table1[Date] )
)
RETURN
SELECTCOLUMNS (
MaxDates,
"ClientNo", [ClientNo],
"Year", [Year],
"Type", LOOKUPVALUE (
Table1[Type],
Table1[ClientNo], [ClientNo],
Table1[Date], [MaxDate]
)
)
In calculating the variable, we add a Year column and then calculate the maximal date corresponding to that year.
Then we take that table variable, pick out the ClientNo and Year columns, and look up what the Type corresponding to the MaxDate.
If Note: you want to keep the MaxDate column, replace
[...] SELECTCOLUMNS ( MaxDates, "ClientNo", [ClientNo], "Year", [Year], [...]
with
[...] ADDCOLUMNS ( MaxDates, [...]

Related

DAX previous year date calculation not showing correctly in Power BI measure

I have a measure that sums expense amount for the current filtered year. This works as desired.
Expense = CALCULATE(SUM('GL Data'[Amount]),FILTER('GL Data','GL Data'[SubGrp1] = "EXPENSE"))
I want to sum the expense amount for the same time period of prior year. My measure calculates correct data as of 11 months ago, not 1 year ago. It appears to function as if the data calculation is looking at my system date, not the specified date:
Expense PY = CALCULATE([Expense], DATEADD(Dates[Date],-1,YEAR))
I've attempted using -12, -13 and MONTH in the DATEADD but the result doesn't correctly total 1 year ago. I've also tried SAMEPERIODLASTYEAR() which provides wrong info. Perhaps my Expense measure is the culprit.
My Date table is generated with this Dax:
Could you please use this as your date table, and test it. In your date table, you imposed no restrictions on the calendar auto() functions which I think is not useful. Also You used Generate function which ignores rows with blank values. In such a case, use GENERATEALL() function; but You need to form your date table like this:
Date =
VAR MinYear =
YEAR ( MIN ( Fact_Table[Date_Column] ) )
VAR MaxYear =
YEAR ( MAX ( Fact_Table[Date_Column] ) )
RETURN
ADDCOLUMNS (
FILTER (
CALENDARAUTO ( 12 ),
AND ( YEAR ( [Date] ) >= MinYear, YEAR ( [Date] ) <= MaxYear )
),
"Calendar Year", "CY " & YEAR ( [Date] ),
"Day", FORMAT ( [Date], "dddd" ),
"Month Number", MONTH ( [Date] ),
"Month", FORMAT ( [Date], "mmmm" ),
"Year Month", FORMAT ( [Date], "mmm yy" ),
"Year", FORMAT ( [Date], "YYYY" )
)
After creating your Date Table, please do not forget to mark it as date table which is a good DAX practice as in the photo below.

DAX Average of Distinct Count Over two tables

I have two tables (Sales,Stock) both have a DateKey and ProductCode. The requirement is to count the Distinct ProductCodes across both tables by Financial week driven by a custom Date Dimension. There is a further requirement to take the Average of the Weekly Distinct counts if multiple weeks are selected not the distinct count for all weeks.
The below DAX works in my unit tests, however on real data volumes (300+ million rows imported) it grinds to a complete standstill. If I select a week it takes about 5 sec, for 12 months its 60 seconds. They need to do YoY and WoW calcs so this perfomance will not be good enough. Not sure how else to achieve this.
Here is the DAX I've written:
Option Count =
// Get options at a week level for Sales
VAR SalesOptions =
SELECTCOLUMNS (
Sales,
"Week",
CALCULATE (
MAX ( Dates[Financial Year Week Number] ),
FILTER ( ALL ( Dates ), Sales[DimBilledDateSKey] = Dates[DimDateSKey] )
),
"ProductOptionCode", 'Sales'[ProductOptionCode]
)
// Get options at a week level for Stock
VAR StockOptions =
SELECTCOLUMNS (
Stock,
"Week",
CALCULATE (
MAX ( Dates[Financial Year Week Number] ),
FILTER ( ALL ( Dates ), Stock[DimDateSKey] = Dates[DimDateSKey] )
),
"ProductOptionCode", 'Stock'[ProductOptionCode]
)
// Union the options from both and then apply a distinct so that a count of the product code would be the same result as a distinct count
VAR CombinedOptions = DISTINCT ( UNION ( SalesOptions, StockOptions ) )
RETURN
// Average the weekly disitnct option count
AVERAGEX(
// Group the above union by week and do a count of the options for the week. They should now be distinct due to the distinct applied to the union
GROUPBY(CombinedOptions, [Week], "Week Option Count", COUNTX(CURRENTGROUP(), [ProductOptionCode] )),
[Week Option Count]
)
I built a small model with a fake Dates dimension and Stock and Sales fake tables
Dates =
SELECTCOLUMNS(
CALENDAR(
"2020-01-05",
"2020-12-26"
),
"DimDateSKey", [Date],
"Financial Year", YEAR( [Date] ),
"Financial Year Week Number",
INT( ( [Date] - "2020-01-05" ) / 7 ) + 2
)
Sales = DATATABLE(
"DimBilledDateSKey", DATETIME,
"ProductOptionCode", INTEGER,
{
{"2020-01-05", 1},
{"2020-01-06", 1},
{"2020-01-06", 2},
{"2020-01-12", 1}
}
)
Stock = DATATABLE(
"DimDateSKey", DATETIME,
"ProductOptionCode", INTEGER,
{
{"2020-01-09", 1},
{"2020-01-06", 3},
{"2020-01-08", 3},
{"2020-01-13", 2}
}
)
With the two relationship over the dates it's easy to filter for the fiscal week, this avoids the need to iterate over the full Date table.
To calculate the average number of the distinct product codes it's enough to iterate over the selected Financial Year Week Number and then compute the COUNTROWS of the DISTINCT of the UNION of the Sales[ProductOptionCode] and the Stock[ProductOptionCode] for the currently iterated week
Option Count =
AVERAGEX (
VALUES( Dates[Financial Year Week Number] ),
CALCULATE (
COUNTROWS (
DISTINCT(
UNION (
VALUES( Sales[ProductOptionCode] ),
VALUES( Stock[ProductOptionCode] )
)
)
)
)
)
If the real model doesn't contain the relationship with the DimBilledDateSKey, maybe because there already is another relationship with another dateKey in the Sales table, it's always possible to add an inactive relationship to be activated with USERLATIONSHIP inside the CALCULATE.
It should be faster, since it uses relationships, that are usually the best option from the performance point of view and minimizes the usage of Set functions, that are expensive, since they materialize the tables in memory.

The last day of month from the last date with sales

How can I get the last day of month from the last date with sales? I want the result to be returned as a DAX calculated table.
The first step, calculated table:
LastDate = LASTNONBLANK( T[Date], CALCULATE( SUM( T[Amount] ) ) )
It returns a table (one column, one row) with the last date with sales. So far, correct, as expected. Say the last day with sales is 2020-04-15. But I want the end of month so 2020-04-30.
I hoped this should work, but it doesn't.
LastDate =
ENDOFMONTH (
LASTNONBLANK (
T[Date],
CALCULATE ( SUM ( T[Amount] ) )
)
)
It still returns 2020-04-15, instead of expected 2020-04-30.
The problem is caused by using dates from table T. Instead, you need to use dates from the calendar table, because list of dates for the time intelligence functions must be continuous.
Assuming you have a properly designed and connected calendar table 'Date' in your data model, change your DAX to:
LastDate =
ENDOFMONTH (
LASTNONBLANK (
Date[Date],
CALCULATE ( SUM ( T[Amount] ) )
)
)
ENDOFMONTH will use now a different table (Date), because LASTNONBLANK function will keep data lineage to it.

Using summarize and userelationship to generate a sum based on a condition

Story:
I have two date columns in my fact table, one is for orderdate and the second is for orderdate/refund/cancelled date.
I created two relationships between the date table and the fact table.
Active: Date > OrderDate
Inactive: Date > OtherDate
I would like to sum the # of refunds per day using the inactive relationship.
What I tried:
Returns =
VAR summary =
SUMMARIZE (
FILTER ( Query1, Query1[kind] = "refund" ),
Query1[orderId],
"returns", MAX ( Query1[amount] )
)
RETURN
CALCULATE (
MAX ( Query1[amount] ),
USERELATIONSHIP ( Query1[OtherDate], DateTable[Date] ),
summary
)
For some reason, it's using the active date column. Any suggestion on how to fix the above formula?
I'm not sure I understand how you are intending to use the summary variable here, but note that USERELATIONSHIP doesn't affect it at all since it's already computed.
You might not need that variable at all. Try this:
Returns =
CALCULATE (
MAX ( Query1[amount] ),
USERELATIONSHIP ( Query1[OtherDate], DateTable[Date] ),
Query1[kind] = "refund"
)

DAX moving average not working

I try to calculate moving average in DAX power bi. I use different codes, for example this.
Moving AverageX 7B Days =
AVERAGEX (
DATESINPERIOD(
sahkoInput[Date];
LASTDATE ( sahkoInput[Date]);
-7;
DAY
);
sahkoInput[price]
)
All codes give the same result - Moving AverageX 7B Days is equal to column "price". What went wrong and how to fix it?
Firstly, I would look to add a date/calendar table to your data model.
This can be as simple as a list of consecutive dates from at least seven days before your first data point until after the end of when you expect your last one to be.
The reason for this is that the date functions in DAX always work best when they have a table of consecutive dates to look at - you can get unpredictable results when your fact table doesn't have any data on a particular date.
Once you have added the date table, create a relationship to link the date column in your sahkoInput table to the date column in your date table.
Now, the following measure should work:
Moving AverageX 7B Days =
CALCULATE (
AVERAGE('sahkoInput'[Price]);
DATESINPERIOD ('DateTable'[Date];
LASTDATE ('DateTable'[Date]);
-7;
DAY)
)
Create a date table, this will dramatically improve performance and increase readability. You can do that by using the following DAX:
Min Date := MIN('sahkoInput'[Date])
Max Date := MAX('sahkoInput'[Date])
Dates :=
VAR BaseCalendar =
CALENDAR ( [Min Date], [Max date] )
RETURN
GENERATE (
BaseCalendar,
VAR BaseDate = [Date]
VAR YearDate =
YEAR ( BaseDate )
VAR MonthNumber =
MONTH ( BaseDate )
RETURN
ROW (
"Day", BaseDate,
"Year", YearDate,
"Month Number", MonthNumber,
"Month", FORMAT ( BaseDate, "mmmm" ),
"Year Month", FORMAT ( BaseDate, "mmm yy" )
)
)
Then referencing this date table you can create an average using the standard average function, like so:
Moving Average 7 Days :=
CALCULATE (
AVERAGE ( 'sahkoInput'[Price] );
KEEPFILTERS ( DATESINPERIOD ( 'Dates'[Date]; MAX ( 'Dates'[Date] ); -7; DAY ) )
)
I hope this helps!