Forum Discussion
Compare customer change between two dates from account table
Hello everyone!
I am new to Power BI, like it very much so far, but now I am struggling with data aggegation and comparison.
Example:
I have an account table that also includes some information about the customers the accounts belong to and different reference dates (the Primary Key is Date, AccountNr and CustomerNr). Now I want to be able to determine the exposure amount of the customers that defaulted between date 1 and date 2 (these different dates can be changed manually by the user).
What I’ve done so far:
Deriving from an introductory video I’ve created a customer table in the report using the following approach:
- Add two date tables (TabDateCurrent and TabDateCompare) with the available dates and create inactive relationships with the account table (colum date)
- Create measures for the DefaultStatus (0=no,1=yes, defaulted) at current date (date 1) and comparison date (date 2), so something like
- DefaultStatusCurrent = CALCULATE(max('TabAccounts'[DefaultStatus]),all('TabDate'),USERELATIONSHIP('TabDateCurrent' [CurrentDate], 'TabAccounts' [Date]))
- DefaultStatusComparison = CALCULATE(max('TabAccounts'[DefaultStatus]),all('TabDate'),USERELATIONSHIP('TabDateComparison' [ComparisonDate], 'TabAccounts' [Date]))
- Create measures for exposure at current date and comparison date
- ExposureCurrent = CALCULATE(sum('TabAccounts' [Exposure]),all('TabDate'),USERELATIONSHIP('TabDateCurrent' [CurrentDate], 'TabAccounts' [Date]))
- ExposureComparison = CALCULATE(sum('TabAccounts' [Exposure]),all('TabDate'),USERELATIONSHIP('TabDateComparison' [ComparisonDate], 'TabAccounts' [Date]))
- Create a Table in the report that includes (among further infos to be added later)
- the Customer number
- exposure at current date
- exposure at comparison date
- filters of DefaultStatusCurrent = 1 and DefaultStatusComparison = 0
- two slicers to change the two dates
This works for the specific customer table in the report, I am able to dynamically change dates and filter the underlying account groups.
However, I also need this information in different visualisations, for instance I want to see the current exposure of all newly defaulted customers as a Card or visualize the new defaults by individual default classes. Without the Customer Nr in my visualisation, my filters do not work.
Do you know any way to (efficiently) achieve this goal using DAX or any other technique?
Thank you!
Hi , ChrisCBR
For the column , we need the static fields. Due to we can not put the measure on the headers . So we need to create two dimention table.
Here are the steps you can refer to :
(1)We need to click "New Table" to create two tables:
Row = VALUES('Table'[RatingGrade])Column = VALUES('Table'[RatingGrade])(2)Then we need to create two measures:
Expouser 1-1 = var _row =SELECTEDVALUE('Row'[RatingGrade]) var _column = SELECTEDVALUE('Column'[RatingGrade]) var _date1 = SELECTEDVALUE('Date1'[Date1]) var _date2 = SELECTEDVALUE('Date2'[Date2]) var _row_t = FILTER( 'Table' , 'Table'[Date] =_date1 && 'Table'[Defaulted]=1) var _column_t = FILTER('Table','Table'[Date] =_date2 && 'Table'[Defaulted]=0) var _row_customerNumber = MAXX(FILTER(_row_t , [RatingGrade] = _row),[CustomerNumber]) var _column_customerNumber = MAXX(FILTER(_column_t , [RatingGrade] = _column),[CustomerNumber]) var _in_customnumber =INTERSECT( SELECTCOLUMNS(_row_t , "CustomerNumber",[CustomerNumber]) , SELECTCOLUMNS(_column_t , "CustomerNumber",[CustomerNumber])) var _row_value =DISTINCT(SELECTCOLUMNS( FILTER(_row_t , [CustomerNumber] in _in_customnumber ) , "RatingGrade",[RatingGrade])) var _column_value = DISTINCT(SELECTCOLUMNS( FILTER(_column_t , [CustomerNumber] in _in_customnumber ) , "RatingGrade",[RatingGrade])) var _value =SUMX( FILTER( _row_t,[RatingGrade] = _row) , [Exposure]) return IF(_row in _row_value && _column in _column_value && _row_customerNumber=_column_customerNumber, _value , BLANK())Expouser 1-2 = var _row =SELECTEDVALUE('Row'[RatingGrade]) var _column = SELECTEDVALUE('Column'[RatingGrade]) var _date1 = SELECTEDVALUE('Date1'[Date1]) var _date2 = SELECTEDVALUE('Date2'[Date2]) var _row_t = FILTER( 'Table' , 'Table'[Date] =_date1 && 'Table'[Defaulted]=1) var _column_t = FILTER('Table','Table'[Date] =_date2 && 'Table'[Defaulted]=0) var _row_customerNumber = MAXX(FILTER(_row_t , [RatingGrade] = _row),[CustomerNumber]) var _column_customerNumber = MAXX(FILTER(_column_t , [RatingGrade] = _column),[CustomerNumber]) var _in_customnumber =INTERSECT( SELECTCOLUMNS(_row_t , "CustomerNumber",[CustomerNumber]) , SELECTCOLUMNS(_column_t , "CustomerNumber",[CustomerNumber])) var _row_value =DISTINCT(SELECTCOLUMNS( FILTER(_row_t , [CustomerNumber] in _in_customnumber ) , "RatingGrade",[RatingGrade])) var _column_value = DISTINCT(SELECTCOLUMNS( FILTER(_column_t , [CustomerNumber] in _in_customnumber ) , "RatingGrade",[RatingGrade])) var _value =SUMX( FILTER( _column_t,[RatingGrade] = _column) , [Exposure]) return IF(_row in _row_value && _column in _column_value && _row_customerNumber=_column_customerNumber, _value , BLANK())(3)Then we put the fields we need on the visual and we will meet your need:
Thank you for your time and sharing, and thank you for your support and understanding of PowerBI!
Best Regards,
Aniya Zhang
If this post helps, then please consider Accept it as the solution to help the other members find it more quickly
11 Replies
- v-yueyunzh-msft
Community Support
Hi, ChrisCBR
Thank you for your experience and technical sharing! For the "current exposure of all new default customers in the form of a card", but you mentioned that you don't have a customer number in your visualization, which means that the basis for grouping does not exist, but if you also want to see the values of some new default customers and show them in the measure, I think the only solution is to write measure to place the grouping of your new default customers in the context of measure. If convenient, you can also provide some simple sample data and the expected output you want for us to do some analysis and review to help you confirm whether it is possible to implement this feature in Power BI.
And this situation is very normal in Power BI, Card's calculation filter context is calculated according to the global context by default, and it is normal that the measures put into other visuals before are not applicable, and the way to solve this is to create new measures written according to your logic.
Best Regards,
Aniya Zhang
If this post helps, then please consider Accept it as the solution to help the other members find it more quickly
- ChrisCBR
Helper I
Thank you for your answer! I understood why it did not work after seeing the result. 🙂
I prepared some example data and some scenarios which results I would expect:
Example:
Date AccountNr CustomerNumber AccountProduct Exposure Defaulted RatingGrade 30.09.2022 1 1 Loan 130 0 D 30.09.2022 2 1 Bonds 5.000 0 D 30.09.2022 3 2 Loan 32.000 0 A 30.09.2022 4 3 Loan 8.000.000 1 FFF 30.09.2022 5 3 Derivatives 500.000 1 FFF 30.09.2022 6 4 Bonds 48.000.000 1 FF 30.09.2022 7 3 Loan 900.000 1 FFF 30.06.2022 1 1 Loan 120 1 F 30.06.2022 2 1 Bonds 4.000 1 F 30.06.2022 3 2 Loan 30.000 0 A 30.06.2022 4 3 Loan 9.000.000 0 C 30.06.2022 5 3 Derivatives 500.000 0 C 30.06.2022 6 4 Bonds 50.000.000 1 FF 31.03.2022 1 1 Loan 100 1 F 31.03.2022 2 1 Bonds 5.000 1 F 31.03.2022 3 2 Loan 30.000 0 A 31.03.2022 4 3 Loan 9.000.000 0 C 31.03.2022 5 3 Derivatives 500.000 0 C 31.03.2022 6 4 Bonds 50.000.000 0 D The primary key for the account table is Date, AccountNr and CustomerNumber.
AccountProduct and the exposure come from the individual accounts, Defaulted and RatingGrade info from the customer.
When date1 (the date for default status = 1) is 30.09.2022 and date2 (the date for default status = 0) is 30.06.2022, the sum of the exposure @date1 (newly in default) would be 9.400.000, exposure from @date2 would be 9.500.000 (coming from customer 3 that newly defaulted between @ date2 and @date1).
----
When date1 (the date for default status = 1) is 30.09.2022 and date2 (the date for default status = 0) is 31.03.2022, the sum of the exposure @date1 newly in default would be 57.400.000, exposure from @date2 would be 59.500.000 (coming from customers 3 and 4 that newly defaulted between @ date2 and @date1).
When I filter the products to loans, the result would be exposure@date1 = 8.900.000 and exposure@date2 = 9.000.000 (only coming from customer 3’s loan; the accounts other than loans would not be part of the calculation).
----
When I turn the whole thing around and date1 is 31.03.2022 (now the older one) and date2 is 30.09.2022, the sum of the exposure@date1 would be 5.100, exposure@date2 would be 5.130 (coming from customer 1 that recovered from default between @date2 and @date1.
I think I would need something like two customers tables (one for each date) that are derived by the account table and dynamically adjust when filters in the underlying account table are set and a join between these two new tables by customer number to accomplish this. I have quite a few similar applications where I would need this.
However, I do not know how to achieve this in DAX or whether there might be a more elegant solution. Above mentioned way was always a very demanding query in a different BI tool we are trying to retire.
Best regards,
Chris
Edit: the example data looks a bit strange and whenever I try to change it to "allign center" I get an HTML error message and it changes it back. The AccountNr is the number close to the date.
- ChrisCBR
Helper I
My original post is gone (?), so here we go again:
Thank you for your answer! I understand why it did not work after seeing the result. 😉
I prepared some example data and some scenarios which results I would expect:
Example:
Date AccountNr CustomerNumber AccountProduct Exposure Defaulted RatingGrade 30.09.2022 1 1 Loan 130 0 D 30.09.2022 2 1 Bonds 5.000 0 D 30.09.2022 3 2 Loan 32.000 0 A 30.09.2022 4 3 Loan 8.000.000 1 FFF 30.09.2022 5 3 Derivatives 500.000 1 FFF 30.09.2022 6 4 Bonds 48.000.000 1 FF 30.09.2022 7 3 Loan 900.000 1 FFF 30.06.2022 1 1 Loan 120 1 F 30.06.2022 2 1 Bonds 4.000 1 F 30.06.2022 3 2 Loan 30.000 0 A 30.06.2022 4 3 Loan 9.000.000 0 C 30.06.2022 5 3 Derivatives 500.000 0 C 30.06.2022 6 4 Bonds 50.000.000 1 FF 31.03.2022 1 1 Loan 100 1 F 31.03.2022 2 1 Bonds 5.000 1 F 31.03.2022 3 2 Loan 30.000 0 A 31.03.2022 4 3 Loan 9.000.000 0 C 31.03.2022 5 3 Derivatives 500.000 0 C 31.03.2022 6 4 Bonds 50.000.000 0 D (account Nr is close to the date, can't seem to be able to adjust the allignment for some reason)
The primary key for the account table is Date, AccountNr and CustomerNumber.
AccountProduct and the exposure come from the individual accounts, Defaulted and RatingGrade info from the customer.
When date1 (the date for default status = 1) is 30.09.2022 and date2 (the date for default status = 0) is 30.06.2022, the sum of the exposure @date1 (newly in default) would be 9.400.000, exposure from @date2 would be 9.500.000 (coming from customer 3 that newly defaulted between @ date2 and @date1.
----
When date1 (the date for default status = 1) is 30.09.2022 and date2 (the date for default status = 0) is 31.03.2022, the sum of the exposure @date1 newly in default would be 57.400.000, exposure from @date2 would be 59.500.000 (coming from the customers 3 and 4 that newly defaulted between @ date2 and @date1.
When I filter the products to loans, the result would be exposure @date1 = 8.900.000 and exposure @date2 = 9.000.000 (only coming from customer 3’s loan; the accounts other than loans would not be part of the calculation).
----
When I turn the whole thing around and date1 is 31.03.2022 (now the older one) and date2 is 30.09.2022, the sum of the exposure @date1 would be 5.100, exposure from @date2 would be 5.130 (coming from customer 1 that recovered from default between @date2 and @date1.
I think I would need something like two customers tables (one for each date) that are derived by the account table and dynamically adjust when filters in the underlying account table are set and a join between these two new tables by customer number to accomplish this. I have quite a few similar applications where I would need this.
However, I am not sure how to achieve this in DAX or whether there might be a more elegant solution since this way it always was a very demanding query in a different BI tool we are trying to retire.
Plus: I've also just read that dynamic aggregated tables are not possible in Power BI?
- v-yueyunzh-msft
Community Support
Hi , ChrisCBR
Accoding to your table you provides , i have some questions about it and i can noy understand.
(1)"AccountProduct and the exposure come from the individual accounts, Defaulted and RatingGrade info from the customer.", the table you provide means that it come from three tables?
(2)"When date1 (the date for default status = 1) is 30.09.2022 and date2 (the date for default status = 0) is 30.06.2022, the sum of the exposure @date1 (newly in default) would be 9.400.000, exposure from @date2 would be 9.500.000 (coming from customer 3 that newly defaulted between @ date2 and @date1."
According to your description, i cannot calcualte the 9.400.000 and 9.500.000 by your provided data.
If this , can you provide all the test table and with data to us and the relationship between them , then put the end result and the calculation logic so that we can help you better.
Thank you for your time and sharing, and thank you for your support and understanding of PowerBI!
Best Regards,
Aniya Zhang
If this post helps, then please consider Accept it as the solution to help the other members find it more quickly
- ChrisCBR
Helper I
Hello!
Regarding your questions:
1) I have an account table with the information which customers the accounta are linked to. The information whether a customer defaulted (=went bankrupt) and the customer rating originally came from a customer table, the information is added to the account table through the customer number, and is therefore always the same for each customer row per date. This was done in data preparation way before I load the data into Power BI.
2) The new default between 30.06.2022 and 30.09.2022 is customer 3 (default status =1 at 30.09.2022 and 0 at 30.06.2022).
The accounts that are linked to customer 3 at 30.09.2022 are AccountNr 4,5 and 7 which have an overall exposure of 9.400.000. At 30.06.2022, the accounts 4 and 5 were linked to customer 3 with an overall exposure of 9.500.000.
Customers 1 and 2 are not in default at 30.09.2022. Customer 4 was already in default by 30.06.2022 and is therefore not a new default between 30.06.2022 and 30.09.2022.
I have no other data in my model except for this account table (there are some other tables with other information, but those have nothing to do with the account table). The only other two tables that are linked to the account table are the two date tables with its inactive relationships that I've mentioned in my original post to calculate the new defaults as a customer list.
SQL queries on the example data for these four scenarios would look like the following if that helps:
--1) default between 30.09.2022 and 30.06.2022
SELECT sum(Exposure1) Exposure1
,sum(menge.Exposure2) Exposure2
from (
SELECT a.*,b.Exposure2 FROM (
SELECT CustomerNumber
,Defaulted
,sum(Exposure) Exposure1
from exampledata
where Defaulted=1
and Date='20220930'
GROUP BY CustomerNumber
,Defaulted
)a
INNER JOIN (
SELECT CustomerNumber
,Defaulted
,sum(Exposure) Exposure2
from exampledata
where Defaulted=0
and Date='20220630'
GROUP BY CustomerNumber
,Defaulted
)b on b.CustomerNumber = a.CustomerNumber
)menge
--2) default between 30.09.2022 and 31.03.2022SELECT sum(Exposure1) Exposure1
,sum(menge.Exposure2) Exposure2
from (
SELECT a.*,b.Exposure2 FROM (
SELECT CustomerNumber
,Defaulted
,sum(Exposure) Exposure1
from exampledata
where Defaulted=1
and Date='20220930'
GROUP BY CustomerNumber
,Defaulted
)a
INNER JOIN (
SELECT CustomerNumber
,Defaulted
,sum(Exposure) Exposure2
from exampledata
where Defaulted=0
and Date='20220331'
GROUP BY CustomerNumber
,Defaulted
)b on b.CustomerNumber = a.CustomerNumber
)menge
--3) default between 30.09.2022 and 31.03.2022 - Loans
SELECT sum(Exposure1) Exposure1
,sum(menge.Exposure2) Exposure2
from (
SELECT a.*,b.Exposure2 FROM (
SELECT CustomerNumber
,Defaulted
,sum(Exposure) Exposure1
from exampledata
where Defaulted=1
and Date='20220930'
and AccountProduct='Loan'
GROUP BY CustomerNumber
,Defaulted
)a
INNER JOIN (
SELECT CustomerNumber
,Defaulted
,sum(Exposure) Exposure2
from exampledata
where Defaulted=0
and Date='20220331'
and AccountProduct='Loan'
GROUP BY CustomerNumber
,Defaulted
)b on b.CustomerNumber = a.CustomerNumber
)menge
--4) cured customer between 31.03.2022 and 30.09.2022SELECT sum(Exposure1) Exposure1
,sum(menge.Exposure2) Exposure2
from (
SELECT a.*,b.Exposure2 FROM (
SELECT CustomerNumber
,Defaulted
,sum(Exposure) Exposure1
from exampledata
where Defaulted=1
and Date='20220331'
GROUP BY CustomerNumber
,Defaulted
)a
INNER JOIN (
SELECT CustomerNumber
,Defaulted
,sum(Exposure) Exposure2
from exampledata
where Defaulted=0
and Date='20220930'
GROUP BY CustomerNumber
,Defaulted
)b on b.CustomerNumber = a.CustomerNumber
)menge
Thanks in advance for your time!
Chris
- ChrisCBR
Helper I
Impressive!
Thank you for the solution, I've learned a lot!