Lookup value based on group max value in PowerBI - powerbi

I would like to first state that I am a beginner with DAX and this is one of my attempts (which seemed to be the closest to the solution I need). I come from a SQL heavy background so my "thinking" is somehow fixed in that way.
I have tried to solve this by implementing something that would match the following SQL logic:
CASE WHEN MAX(column) OVER (PARTITION BY group) = column2 THEN column3 ELSE "" END
However, this doesn't seem to work directly like in SQL, so I would like to ask for some help.
I have the current set of data, which is imported from a simple text file.
ID GroupID Amount
1 2 8502
2 2 8502
3 2 8502
4 2 8502
1 6 80
2 6 80
And I would like to find a way to get the following result:
ID GroupID Amount LatestGroupAmount
1 2 8502
2 2 8502
3 2 8502
4 2 8502 8502
1 6 80
2 6 80 80
And then have a Total under LatestGroupAmount, totaling to 8582.
So far, I have created 2 new measures in my table, MaxID and MaxIDbyGroup.
MaxID = MAX(data[ID])
and
MaxIDbyGroup = CALCULATE([MaxID], ALLEXCEPT(data, data[GroupID]))
This gives me:
ID GroupID Amount MaxID MaxIDbyGroup
1 2 8502 1 4
2 2 8502 2 4
3 2 8502 3 4
4 2 8502 4 4
1 6 80 1 2
2 6 80 2 2
Now, I would like to create a new measure that just does a lookup of the Amount, based on the equality between ID and MaxIDbyGroup.
I have tried to create a new measure with the following definition:
LatestGroupAmount = LOOKUPVALUE(data[Amount], data[GroupId], data[MaxIDbyGroup])
But this gives me the following output:
ID GroupID Amount LatestGroupAmount
1 2 8502
2 2 8502
3 2 8502
4 2 8502
1 6 80 8502
2 6 80 8502
Edit:
I have created another measure:
MaxGrid = MAX(data[GroupID])
And I have tried using CALCULATE with the following definition for LatestGroupAmount:
LatestGroupAmount = CALCULATE(
SUM( data[Amount] ),
FILTER( data, data[ID] = data[MAXID_by_author]), FILTER(data, data[GroupID] = data[MaxGrid]) )
And it seems to show what I want, however, it filters the 6 rows I have to only 2 rows (although I think it does an aggregation).
ID GroupID Amount LatestGroupAmount
4 2 8502 8502
2 6 80 80
The reason I say I think it's an aggregation, is because I add the MaxID to the widget, the output shows the correct number of rows. Essentially, the image below is the output that I want, except for the MaxID column.
If I remove the MaxID column, the widget automatically summarizes to two rows, but I want to show all of the 6 rows.

You can use this measure to achieve your result:
LatestGroupAmount =
VAR TT01 = ADDCOLUMNS(
SUMMARIZE(Data,Data[ID],Data[GroupID]),
"MaxID",CALCULATE(MAX(Data[ID]),ALLEXCEPT(Data,Data[GroupID]))
)
RETURN
CALCULATE(MAX(Data[Amount]),
FILTER(TT01,
Data[ID] =[MaxID]))
Then define your visual table by putting [ID], [GroupID],[Amount] on rows, and above measure into values, Then:
Please Make sure that For [ID] and [GroupID Columns], show items with no data is ticked or checked, like in the picture below.

Your current definition for LatestGroupAmount is searching in the GroupId column, though I believe that should be the ID column, i.e.:
LOOKUPVALUE( data[Amount], data[ID], data[MaxIDbyGroup] )
In any case, this will fail since that column contains duplicate entries. As such, you should use something like:
LatestGroupAmount :=
CALCULATE(
MAX( data[Amount] ),
FILTER( data, data[Id] = data[MaxIDbyGroup] )
)

Related

Latest values by category based on a selected date

First, as I am a French guy, I want to apologise in advance for my poor English!
Despite my searches since few days, I cannot find the correct measure to solve my problem.
I think I am close to the solution, but I really need help to achieve this job!
Here is my need:
I have a dataset with a date table and a "Position" (i.e. "stock") table, which is my fact table, with date column.
Classic relationship between these 2 tables. Many Dates in "Position" table / 1 date un "Dates" table.
My "Dates" table has a one date per day (Column "AsOf")
My "Deals" table looks like this:
Id
DealId
AsOfDate
Notional
10000
1
9/1/2022
2000000
10001
1
9/1/2022
3000000
10002
1
9/1/2022
1818147
10010
4
5/31/2022
2000000
10011
4
5/31/2022
997500
10012
4
5/31/2022
1500000
10013
4
5/31/2022
1127820
10014
5
7/27/2022
140000
10015
5
7/27/2022
210000
10016
5
7/27/2022
500000
10017
5
7/27/2022
750000
10018
5
7/27/2022
625000
10019
1
8/31/2022
2000000
10020
1
8/31/2022
3000000
10021
1
8/31/2022
1801257
10022
1
8/31/2022
96976
10023
1
8/31/2022
1193365
10024
1
8/31/2022
67883
Based on a selected date (slicer with all dates from "Dates" table), I would like to calculate the sum of Last Notional for each "Deal" (column "DealId").
So, I must identify, for each Deal, the last "Asof Date" before or equal to the selected date and sum all matching rows.
Examples:
If selected date is 9/1/2022, I will see all rows, except rows asof date = 8/31/2022 for deal 1 (as the last date for this deal is 9/1/2022).
So, I expect to see:
DealId Sum of Notional
1 6 818 147
4 5 625 320
5 2 225 000
Grand Total 14 668 467
If I select 8/31/2022, total for Deal 1 changes (as we now take rows of 8/31 instead of 1/9):
DealId Sum of Notional
1 8 159 481
4 5 625 320
5 2 225 000
Grand Total 16 009 800
If I select 7/29, only deals 4 and 5 are active on this date, so the results should be:
DealId Sum of Notional
4 5 625 320
5 2 225 000
Grand Total 7 850 320
I think I found a solution for the rows, but my total is wrong (only notionals of the selected date are totalized).
I also think my measure is incorrect if I try to display the notional amounts aggregated by Rating (other column in my table) instead of deal.
Here is my measure:
Last Notional =
VAR SelectedAsOf =
SELECTEDVALUE ( Dates[AsOf] )
VAR LastAsofPerDeal =
CALCULATE (
MAX ( Deals[AsOf Date] ),
FILTER ( ALLEXCEPT ( Deals, Deals[DealId] ), Deals[AsOf Date] <= SelectedAsOf )
)
RETURN
CALCULATE (
SUM ( Deals[Notional] ),
FILTER (
ALLEXCEPT ( Deals, Deals[DealId]),
LastAsofPerDeal = Deals[AsOf Date]
)
)
I hope it is clear for you, and you will be able to find a solution for this.
Thanks in advance.
Antoine
Make sure you have no relationship between your calendar table and deals table like so.
Create a slicer with your dates table and create a table visual with deal id. Then add a measure to the table as follows:
Sum of Notional =
VAR slicer = SELECTEDVALUE(Dates[Date])
VAR tbl = FILTER(Deals,Deals[AsOfDate] <= slicer)
VAR maxBalanceDate = CALCULATE(MAX(Deals[AsOfDate]),tbl)
RETURN
CALCULATE(
SUM(Deals[Notional]),
Deals[AsOfDate] = maxBalanceDate
)

DAX measure for Sum of values on the first and last day of a cycle

I have a table 'fact WorkItems', where changes made to items are saved on the day of the change ([ChangedDate]).
WorkItemId
AreaPath
ChangedDate
State
StoryPoints
IterationPath
1day
14day
Commitment
Delivered
1
A
04/01/2022
New
4
24.1
4
1
A
06/01/2022
Ready
6
24.1
6
1
A
10/01/2022
Active
6
24.1
6
1
A
12/01/2022
Testing
8
24.1
8
8
1
A
18/01/2022
Testing
2
24.1
1
A
19/01/2022
Testing
2
24.1
1
A
28/01/2022
Closed
2
24.1
2
1
A
01/02/2022
Closed
2
24.1
2
2
1
A
03/02/2022
Closed
2
24.1
I also have a table called 'dim Itrations', where cycles' start and end dates are kept.
IterationPath
StartDate
EndDate
24.1
13/01/2022
02/02/2022
24.2
03/02/2022
17/02/2022
24.3
18/02/2022
04/03/2022
I have created a measure [1day] which tells me how many [StoryPoints] had an Item on or before a cycle started
1day =
CALCULATE (
SUM( 'fact WorkItems'[StoryPoints] ),
FILTER (
'dim Iterations',
MAX('fact Workitems'[ChangedDate]) <= 'dim Iterations'[StartDate]
)
)
I have also created a measure [14day] which tells me how many [StoryPoints] had an Item by the end of the cycle once it's in "Closed" [State].
14day =
CALCULATE (
SUM( 'fact WorkItems'[StoryPoints] ),
FILTER ('fact WorkItems',
AND(
'fact Workitems'[State]="Closed",
'fact Workitems'[ChangedDate] <= MIN('dim Iterations'[EndDate])
)
))
My objective is to create two measures: [Commitment] and [Delivered] which will sum all the StoryPoints each team ([AreaPath]) had for each of  the cycles exactly on the the day the cycle started and ended (the latter with status closed). I know how to "tell" Power BI to only look at the rows, where Change date = [StartDate] or [ClosedDate].
The problem is when changes to items are made before the start/end date. I'm trying to "fill in those gaps" in the table by telling Power BI to look at the last record which was changed before or on the Start/End Date and to use those values. What I'm trying to achieve is presented in the table. Any ideas?

Power BI Measure to countrows of related values several related tables deep

I need to create a measure for a card that will count the total number of Question Groups that exist for each person using the tables below.
I've tried the following but it's returning the result 10, instead of the expected result which should be 6. (George = 2, Susan = 1, tom = 1, bill=1, sally =1, mark =0, jason=0)
Measure = COUNTROWS(NATURALLEFTOUTERJOIN(NATURALLEFTOUTERJOIN(People,Questions),'Question Groups'))
What am I doing wrong?
Table: People
PeopleID
Name
1
George
2
Susan
3
Tom
4
Bill
5
Sally
6
Mark
7
Jason
Table: relPeopleQuestions
PeopleID
QuestionID
1
1
1
2
1
3
2
4
2
5
3
6
4
7
5
8
Table: Questions
Question ID
Question name
Questiong Group ID
1
How are you?
1
2
Favorite Color?
2
3
Favorite Movie?
2
4
Sister's Name
3
5
Brother's Name
3
6
What is your birthdate?
1
7
What City do you live in?
1
8
Favorite game?
2
Table: Question Groups
Question Group ID
Question Group Name
1
Assorted
2
Favorites
3
Relatives
A working example file can be obtained here.
A distinct count on the Question Group ID from the Questions table would seem to be sufficient, e.g.
MyMeasure =
VAR MyTable =
SUMMARIZE (
People,
People[Name],
"Count", DISTINCTCOUNT ( Questions[Question Group ID] )
)
RETURN
SUMX ( MyTable, [Count] )

Calculating the sum of values in a different table for rows that are between two dates

I have two tables.
A campagin table:
Campaign ID
Start Date
End Date
Daily Target
1
21/12/2020
15/02/2021
5
2
18/10/2020
18/01/2021
3
3
01/07/2020
03/01/2021
8
4
09/01/2021
15/05/2021
1
5
05/08/2020
09/01/2021
2
And a simple Date table:
Date
01/01/2021
02/01/2021
03/01/2021
04/01/2021
05/01/2021
06/01/2021
07/01/2021
08/01/2021
09/01/2021
10/01/2021
11/01/2021
12/01/2021
13/01/2021
What I would like to do is add a calculated column to the Date table that will calculate the sum of all the Daily Targets for campaigns that are between Start Date and End Date. So for 1st January 2021 I want to take the sum of the Daily Targets for Campaign 1, 2, 3 & 5. E.g:
Date
Total Daily Target
01/01/2021
18
02/01/2021
18
03/01/2021
18
04/01/2021
10
05/01/2021
10
06/01/2021
10
07/01/2021
10
08/01/2021
10
09/01/2021
9
10/01/2021
9
11/01/2021
9
12/01/2021
9
13/01/2021
9
I'm quite new to DAX and have tried multiple different variations of SUM(), SUMX() & FILTER() within CALCULATE(), all to no avail. I also don't know what the relationship between the two tables should be seeing as there are two dates in the Campaign table? Any help at all would be greatly appreciated.
Try this below Measure-
Measure =
var current_row_date = MIN('date'[Date])
RETURN
CALCULATE(
SUM(campaign[Daily Target]),
campaign[Start Date] <= current_row_date
&& campaign[End Date] >= current_row_date
)
output-

DAX Grouping and Ranking in Calculated Columns

My raw data stops at sales - looking for some DAX help adding the last two as calculated columns.
customer_id order_id order_date sales total_sales_by_customer total_sales_customer_rank
------------- ---------- ------------ ------- ------------------------- ---------------------------
BM 1 9/2/2014 476 550 1
BM 2 10/27/2016 25 550 1
BM 3 9/30/2014 49 550 1
RA 4 12/18/2017 47 525 3
RA 5 9/7/2017 478 525 3
RS 6 7/5/2015 5 5 other
JH 7 5/12/2017 6 6 other
AG 8 9/7/2015 7 7 other
SP 9 5/19/2017 26 546 2
SP 10 8/16/2015 520 546 2
Lets start with total sales by customer:
total_sales_by_customer =
var custID = orders[customer_id]
return CALCULATE(SUM(orders[sales], FILTER(orders, custID = orders[customer_id]))
first we get the custID, filter the orders table on this ID and sum it together per customer.
Next the ranking:
total_sales_customer_rank =
var rankMe = RANKX(orders, orders[total_sales_by_customer],,,Dense)
return if (rankMe > 3, "other", CONVERT(rankMe, STRING))
We get the rank per cust sales (gotten from first column), if it is bigger than 3, replace by "other"
On your first question: DAX is not like a programming language. Each row is assessed individual. Lets go with your first row: your custID will be "BM".
Next we calculate the sum of all the sales. We filter the whole table on the custID and sum this together. So in the filter we have actualty only 3 rows!
This is repeated for each row, seems slow but I only told this so you can understand the result you are getting back. In reality there is clever logic to return data fast.
What you want to do "Orders[Customer ID]=Orders[Customer ID]" is not possible because your Orders[Customer ID] is within the filter and will run with the rows..
var custid = VALUES(Orders[Customer ID]) Values is returning a single column table, you can not use this in a filter because you are then comparing a cell value with a table.