Would you, please, help me to apply different calculations for 2 rows in power BI:
that is, to transform this table:
client_ids products purchased month
1 0 0 jan
2 1A 1 jan
2 1B 1 jan
3 0 0 jan
4 0 0 jan
5 0 0 feb
into this:
purchased jan feb
1 1
0 3 1
That is, to perform calculations:
-on purchased = 0 - count over month, client
-on purchased = 1 - count distinct over month, client
Thank you.
I used the method:
-create the reference to the main query in the query editor
-drop the column with products
-drop duplicates
But this makes downloading the report slower.
To return the expected output, you can use two steps to obtain the result from the data:
Assuming this is your table with date:
First, calculate the month different compared with today to find recently month (you can try other method depend on your data nature):
Mon Diff = (YEAR(NOW()) - YEAR(Sheet1[date])) + (MONTH(NOW()) - MONTH(Sheet1[date]))
Second, rank the recent month as current:
rank =
var ranking = RANKX(Sheet1,Sheet1[Mon Diff],,,Dense)
return
SWITCH(ranking,1,"prior",2,"current")
Third, generate distinct values from purchase column
Table = DISTINCT(Sheet1[purchased])
Fourth, calculate the frequencies of 0 & 1 in Prior Month, the same for Feb
Jan = CALCULATE(COUNT(Sheet1[rank]),Sheet1[rank]="prior",
Sheet1[purchased]=EARLIER('Table'[purchased]))
Feb = CALCULATE(COUNT(Sheet1[rank]),Sheet1[rank]="current",
Sheet1[purchased]=EARLIER('Table'[purchased]))
The New table for the infor (In Jan, purchase 2 has 2 occurrence instead of 1):
Related
I'm having some trouble with the logic behind a report and was hoping to get some help on how to capture more rows in a table with a date slicer.
I'll start by laying out the structure of my data and what I'm hoping to accomplish
I have a date column that I generated in SQL server. The whole report has to use direct query, so that would be one stipulation for possible solutions.
The date column just has dates like 1/1/2022, 1/2/2022, etc.
DATE
1 / 1 / 2022
1 / 2 / 2022
1 / 3 / 2022
1 / 4 / 2022
The data table is being filtered by a date slicer that uses the dates in the date column, as well as a DAX formula that gets selected values from then slicer.
Here is an example of the data table:
Begin Date
End Date
Data
2 / 30 / 2022
4 / 4 / 2022
0
3 / 6 / 2022
4 / 26 / 2022
0
4 / 7 / 2022
4 / 26 / 2022
0
4 / 30 / 2022
5 / 15 / 2022
0
In this instance, the table I'm filtering has two date columns that I need to filter by, hence the date table. For the data to appear, I'm filtering the slicer with 4-1-2022 to 4-30-2022. Ideally, If at least one date between Begin Date and End Date appears between the range given in the slicer with the date table, the row will appear.
Here is the code for what I have right now:
var range_end = LASTDATE('DATE'[Dates])
var range = DATESBETWEEN('DATE'[Dates], range_start, range_end)
return
if(
(CONTAINSROW(range, SELECTEDVALUE('DATA'[Begin Date])) = TRUE()
|| CONTAINSROW(range, SELECTEDVALUE('DATA'[End Date])) = TRUE()),
1,0)
This DAX is used as a filter on the data table, if it returns 1 for the row, it displays the row.
A problem occurs when I filter by a smaller date range, and I think it's because my code is not picking up as many values as I want it to.
For instance, if I filter the Date column down to 4/1/2022 to 4/2/2022, I return these possible rows:
Begin Date
End Date
Data
4 / 1 / 2022
5 / 13 / 2022
0
4 / 1 / 2022
4 / 26 / 2022
0
4 / 1 / 2022
4 / 26 / 2022
0
4 / 1 / 2022
5 / 15 / 2022
0
But if I expand the filter by a day (4/1/2022 to 4/3/2022) I get a new row:
Begin Date
End Date
Data
3 / 20 / 2022
4 / 3 / 2022
< New row
4 / 1 / 2022
5 / 13 / 2022
0
4 / 1 / 2022
4 / 26 / 2022
0
4 / 1 / 2022
4 / 26 / 2022
0
4 / 1 / 2022
5 / 15 / 2022
0
Ideally, the filter range of 4/1/2022 to 4/2/2022 would have picked up this row already, because it contains 4/2/2022 between it's begin and end date.
I think this is because my code is treating the selected dates as one value, where ideally they would look at all dates between the Begin Date and End Date columns, and see if any one of those dates exist within the specified date range, however my attempts at solving this with DAX have not worked to fix this issue.
Please let me know if there is a way to rewrite or remake my report or DAX to better accomplish the goal of displaying the correct rows. Let me know if I can clarify anything, ad I'll try to answer as best I can (without showing the report)
Thank you!
Can you try this measure?
Measure =
COUNTX (
NATURALINNERJOIN (
DATESBETWEEN (
dateTbl[DATE],
CALCULATE ( MAX ( data[Begin Date] ) ),
CALCULATE ( MAX ( data[End Date] ) )
),
ALLSELECTED ( dateTbl[DATE] )
),
[DATE]
)
COUNTX,NATURALINNERJOIN,DATESBETWEEN,CALCULATE,MAX,ALLSELECTED are supported in DQ.
Is there a recommended Power BI DAX pattern for calculating monthly Days Sales Outstanding (a.k.a. DSO or Debtor Days) using the Countback method?
I have been searching for a while and although there are many asking about it, there is no working solution recommendation I can find. I think that is perhaps because nobody has set out the problem properly so I am going to try to explain as fully as possible.
DSO is a widely-used management accounting measure of the average number of days that it takes a business to collect payment for its credit sales. More background info on the metric here: https://www.investopedia.com/terms/d/dso.asp
There are various options for defining the calculation. I believe my requirement is known as the countback method. My data set is a fairly large star schema with a separate date dimension, but using the below simplified data set to generate a solution would totally point me in the right direction.
Input data set as follows:
Month No
Month
Days in Month
Debt Balance
Gross Income
1
Jan
31
1000
700
2
Feb
28
1100
500
3
Mar
31
900
400
4
Apr
30
950
600
5
May
31
1000
400
6
Jun
30
1100
550
7
Jul
31
900
700
8
Aug
31
950
500
9
Sep
30
1000
400
10
Oct
31
1100
600
11
Nov
30
900
400
12
Dec
31
950
550
The aim is to create a measure for debtor days equal to the number of days of average daily income per month we need to count back to match the debt balance.
Starting with Dec as an example in 3 steps:
Debt Balance= 950, income = 550. Dec has 31 days. So we take all
31 days of income and reduce the debt balance to 400 (i.e. 950 - 550) and go back to the previous month.
Remaining Dec Debt balance =
400. Nov Income = 700. We don't need all of the daily income from Nov to match the rest of the Dec debt balance. 400/700 x 30 days in
Nov = 17.14 days
We have finished counting back days. 31 + 17.14 = 48.14 debtor days
Nov has a higher balance so we need 1 more step:
Debt balance= 1500, income = 700. Nov has 30 days. So we take all 30 days of income and reduce the debt balance to 800 (i.e. 1500 - 700) and go back to the previous month.
Remaining Nov Debt balance = 800. Oct Income = 600. Oct has 31 days. So we take all 31 days of income from Oct and reduce the Nov debt balance to 200 (i.e. 1500 - 700 - 600)
Remaining Nov debt balance = 200. Sep Income = 400. We don't need all of the daily income from Sep to match the rest of the Nov debt balance. 200/400 x 30 days in Sep = 15 days
We have finished counting back days. 30 + 31 + 15 = 76 debtor days
Apr has a lower balance so can be resolved in one step:
Debt Balance = 400, income = 600. Apr has 30 days. We don't need all of Apr Income as income exceeds debt in this month. 400/600 * 30 = 20 debtor days
The required solution for Debtor days in the simplified data set is therefore shown in the right-most "Debtor Days" column as follows:
Month
Month
Days
Debt Balance
Gross Income
Debtor Days
1
Jan
31
1000
700
2
Feb
28
1100
500
54.57
3
Mar
31
900
400
59.00
4
Apr
30
400
600
20.00
5
May
31
600
400
41.00
6
Jun
30
800
550
49.38
7
Jul
31
900
700
41.91
8
Aug
31
950
500
50.93
9
Sep
30
1000
400
65.43
10
Oct
31
1100
600
67.20
11
Nov
30
1500
700
76.00
12
Dec
31
950
550
48.14
I hope the above explains the required calculation sufficiently. Of course it needs to be implemented as a measure rather than a calculated column as in the real world it needs to work with more complex scenarios with the user defining the filter context at runtime by filtering and slicing in Power BI.
If anyone can recommend a DAX calculation for Debtor Days, that would be great!
This works on a small example, probably this may not work on a large model.
There is no easy way to do that, DAX isnt a programing language and we canot use loop / recursive statements etc. We have many limitations;
We can only mimic this behavior by bulk/ force calculate (which is resource consuming task). The most interesting part is variable _zz where we calculate for each row 3 version of the main table limited to 1/2/3 rows (as you see we hardcode some value - i consider that we can find result in max 3 iteration). You can investigate this if you want by adding NewTable from this code:
filter(GENERATE(SELECTCOLUMNS(GENERATE(Sheet1, GENERATESERIES(1,3,1)),"MYK", [MonthYearKey], "MonthToCheck", [Value], "Debt", [Debt Balance]),
var _tmp = TOPN([MonthToCheck],FILTER(ALL(Sheet1), Sheet1[MonthYearKey] <= [MYK] ), Sheet1[MonthYearKey], DESC)
return row("IncomAgg", SUMX(_tmp, Sheet1[Gross Income]) )
), [IncomAgg] >= [Debt])
Next, I try to find in our Table Variable 2 information, how many months back we must go.
Full code (I use MonthYearKey for time navigating purpose):
Mes =
var __currRowDebt = SELECTEDVALUE(Sheet1[Debt Balance])
var _zz = TOPN(1,
filter(GENERATE(SELECTCOLUMNS(GENERATE(Sheet1, GENERATESERIES(1,3,1)),"MYK", [MonthYearKey], "MonthToCheck", [Value], "Debt", [Debt Balance]),
var _tmp = TOPN([MonthToCheck],FILTER(ALL(Sheet1), Sheet1[MonthYearKey] <= [MYK] ), Sheet1[MonthYearKey], DESC)
return row("IncomAgg", SUMX(_tmp, Sheet1[Gross Income]) )
), [IncomAgg] >= [Debt]), [MonthToCheck], ASC)
var __monthinscoop = sumx(_zz,[MonthToCheck]) - 2
var __backwardrunningIncom = sumx(_zz,[IncomAgg])
var _calc = CALCULATE( sum(Sheet1[Days]), filter(ALL(Sheet1), Sheet1[MonthYearKey] <= SELECTEDVALUE( Sheet1[MonthYearKey]) && Sheet1[MonthYearKey] >= SELECTEDVALUE( Sheet1[MonthYearKey]) - __monthinscoop ))
var __twik = SWITCH( TRUE()
, __monthinscoop < 0 , -1
, __monthinscoop = 0 , 1
, __monthinscoop = 1 , 3
,0)
var __GetRowValue = CALCULATE( SUM(Sheet1[Gross Income]), FILTER(ALL(Sheet1), Sheet1[MonthYearKey] = (SELECTEDVALUE( Sheet1[MonthYearKey]) + __monthinscoop - __twik)))
var __GetRowDays = CALCULATE( SUM(Sheet1[Days]), FILTER(ALL(Sheet1), Sheet1[MonthYearKey] = (SELECTEDVALUE( Sheet1[MonthYearKey]) + __monthinscoop - __twik)))
return
_calc+DIVIDE(__GetRowValue - (__backwardrunningIncom - __currRowDebt), __GetRowValue) * __GetRowDays
I have two simple tables. I need to able to determine who is 'new' as of a particular date (say January) and then count only those attributes. There's a 1:M relationship on name. I basically need to answer the following questions with the below data:
What is the total number of FamilyMembers based on log-in for the month? (Done using custom measure)
Out of the total of #1 - how many have logged in for the first time?
Out of the total of #2 - how many were children? How many were adults?
Log In Table
ID
Name
Date
login1
Sam
Jan
login2
Sam
Jan
login3
Dave
Jan
login4
Dave
Jan
login5
Jack
Jan
login6
Sam
Jan
login7
James
Feb
login8
James
Feb
login9
James
Feb
login10
Sam
Feb
login11
Sam
Feb
login12
Steve
Feb
Contact Table
Name
FamilyMembers
Child
Adult
Sam
3
1
2
James
2
1
1
Dave
4
2
2
Jack
1
0
1
Steve
6
1
5
Using this data, filtered on February we would see Steve never signed in prior to that date, so that makes him 'new'. James is also new.
My closest attempt is the custom 'Count of New Individuals' Measure
VAR currentUsers = VALUES('Log-Ins'[Name])
VAR currentDate = MIN('Log-Ins'[Date])
VAR pastUsers = CALCULATETABLE(VALUES('Log-Ins'[Name]),
ALL('Log-Ins'[Date].[Month],'Log-Ins'[Date].[MonthNo],'Log-Ins'[Date].[Year])
, 'Log-Ins'[Date]<currentDate)
VAR newUsers = EXCEPT(currentUsers,pastUsers)
RETURN COUNTROWS(newUsers)
As you can see this gives me the count of new individuals but I want to count their attributes to say :: Out of the 11 total family members, 8 were new. Out of those 8, 6 were adults and 2 were children.
I may be getting lost in the translation, but I don't understand how exactly you want to display the information.
#ContactsWhoLoggedIN :=
CALCULATE(COUNTROWS(Contacts),FILTER(Contacts,CALCULATE(COUNTROWS(LogIN)>0)))
#NewCWhoLoggedIN :=
CALCULATE(COUNTROWS(Contacts),
FILTER(Contacts,
//LoggedIn in the Current Date Context
CALCULATE(COUNTROWS(LogIN))>0
&&
//Never LoogedIN before the Current Date Context
CALCULATE(COUNTROWS(LogIN),FILTER(ALL(Dates),Dates[Date]<MIN(Dates[Date])))=0
)
)
#CWhoLoggedBackIN := [#ContactsWhoLoggedIN]-[#NewCWhoLoggedIN]
#FM_NewCWLI :=
CALCULATE(SUM(Contacts[FamilyMembers]),
FILTER(Contacts,
//LoggedIn in the Current Date Context
CALCULATE(COUNTROWS(LogIN))>0
&&
//Never LoogedIN before the Current Date Context
CALCULATE(COUNTROWS(LogIN),FILTER(ALL(Dates),Dates[Date]<MIN(Dates[Date])))=0
)
)
I remember this pattern from "Microsoft Excel 2013: Building Data Models with PowerPivot"
My Data looks something like this:
ContractID Start Date End Date
1 01.01.2020 23.03.2020
2 15.02.2020 29.07.2020
3 06.06.2020 null
The last contract would be still active. I have a DateTable with the Start Date as the active relationship.
I need the end result too look like this:
Date Active Contracts
Jan 1
Feb 2
Mar 2
Apr 1
May 1
Jun 2
How should the measure look like?
Thanks in advance!
Assuming you have a month in your date table
VAR currentMonth = SELECTEDVALUE(MyDataTable[Month value]) --needs to be a number 1 to 12
RETURN CALCULATE(COUNTROWS(MyDataTable),
ALL(DateTable),
MONTH(MyDataTable[Start Date]) >= currentMonth,
ISBLANK(MyDataTable[End Date]) || MONTH(MyDataTable[End Date]) <= currentMonth)
I am trying to create a variance measure in PowerBI.
This is the data that I have,
Month Year MonthNo Value
Jan 2016 1 700
Feb 2016 2 800
March 2016 3 900
April 2016 4 750
.
.
Jan 2017 13 690
Feb 2017 14 730
And My variance for the Month Number 7 should be like,
`{Avg(values(4,5,6) - Value(7)} / Value(7)`
i.e (Average of last 3 months value - current month value) / Current month value
How to do this in Power BI? Thanks.
If it is okay for you to use a column, I believe you could add one with this code to get what you want:
Variance = (CALCULATE(AVERAGEX(Sheet1,Sheet1[Value]),FILTER(FILTER(Sheet1,Sheet1[MonthNo]<=EARLIER(Sheet1[MonthNo])-1),Sheet1[MonthNo]>=EARLIER(Sheet1[MonthNo])-3))-Sheet1[Value])/Sheet1[Value]
You'll need to replace all instances of Sheet1 with the name of your table.
It'll give you something like this: