Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Register now to learn Fabric in free live sessions led by the best Microsoft experts. From Apr 16 to May 9, in English and Spanish.

Reply
JerryZhou
New Member

Is it possible to create calculated tables by splitting rows in DAX?

Hi friends, 

 

I am looking for some ideas/help on how I can fulfill the following reporting requirement, which basically involves manipulating a table into a more workable format. I know there's probably an easier solution in Power Query, but I am trying to do this in DAX because the existing table was created through DAX. 

 

Here is an example to demonstrate the rules:

 

Below is a list of 4 projects that was sold in the first quarter of the year, and each project can be managed by one or two sales persons.

  1. If a project has 2 salespersons, each salesperson earns half of the revenue amount.
    • (i.e. 50% goes to salesperson A, 50% goes to salesperson B)
  2. If the project has a lead time of more than 40 weeks, the revenue amount needs to be split between the quarter in which it was sold and the following quarter.
    • (i.e. For a large project sold in Q1, 50% goes under Q1, 50% goes under Q2)
  3. The two rules can stack on top of each other, in which case if a project has 2 sales persons and a long lead time, 25% of the revenue will go to each sales person under each of Q1 and Q2. 
    • (i.e. 25% goes to salesperson A under Q1, 25% goes to salesperson B under Q1, 25% goes to salesperson A under Q2, 25% goes to salesperson B under Q2) 

Existing table: 

QuarterProjectRevenueSalespersonSecondary SalespersonLead Time
FY2021Q1P1$1,000A 20
FY2021Q1P2$1,000B 50
FY2021Q1P3$1,000CD20
FY2021Q1P4$1,000EF50

 

Desired format: 

QuarterProjectRevenueSalesperson
FY2021Q1P1$1,000A
FY2021Q1P2$500B
FY2021Q2P2$500B
FY2021Q1P3$500C
FY2021Q1P3$500D
FY2021Q1P4$250E
FY2021Q1P4$250F
FY2021Q2P4$250E
FY2021Q2P4$250F

 

Can anyone please help?

 

I'm not looking for a full solution but I would really appreciate if you can give any direction or mention some functions that I should use to make such transformation. 

 

Thanks!

Jerry

1 ACCEPTED SOLUTION
Anonymous
Not applicable

Hey, I started off with the "Why not?" question and worked on it step by step, starting from your sample data in a table named "Existing Table". I have not thought about the right method, shortest method, optimized method, or anything like that. Just built the code step by step, but got the result.

Existing Table

sreenathv_0-1615279231446.png

Output

sreenathv_1-1615279267524.png


The DAX code for this calculated table is given below, it is quite large, but I have given comments in each step so that you will be able to understand what each step does.

ProjectTable = 
-- Get a list of projects
VAR ListOfProjects = ALLSELECTED(ExistingTable[Project],ExistingTable[Lead Time],ExistingTable[Revenue])
-- Crossjoin the list of projects with another table with one-column and two-rows that contains the list of 2 sales persons (the field name of the new table will be "Value")
VAR LOP_WS =
    GENERATE(
        ListOfProjects,
        VAR CP = [Project]
        VAR SP1 = LOOKUPVALUE(ExistingTable[Salesperson],ExistingTable[Project],CP)
        VAR SP2 = LOOKUPVALUE(ExistingTable[Secondary Salesperson],ExistingTable[Project],CP)
        VAR RN = IF(ISBLANK(SP2),BLANK(),2)
        VAR LOS = { {SP1},{SP2} }
        RETURN
        LOS
    )
-- Rename the "Value" field to "Sales Person" and also filter the blanks out.
VAR X = SELECTCOLUMNS(
FILTER(LOP_WS,[Value]<>""),
"Project",[Project],
"Revenue",[Revenue],
"Lead Time",[Lead Time],
"Sales Person",[Value]
)
--Add an additional row for all projects with more than 50 as the lead time. And an additional column to identify the extra rows. 
--The new field will have 3 values, 0 in the existing rows. 1 in the new field if the project has leadtime>=50, blank() in the new field if the project has <50 lead time.
VAR LOP_WS2 =
    GENERATE(
        X,
        VAR LT = IF([Lead Time]>=50,1,BLANK())
        VAR T = {{0},{LT}}
        return
        T
    )
--Filter out the blanks in the new field and also add the starting quarter of the project as "Start Q"
VAR Output1 = ADDCOLUMNS(FILTER(LOP_WS2,NOT(ISBLANK([Value]))),"Start Q",LOOKUPVALUE(ExistingTable[Quarter],ExistingTable[Project],[Project]))

-- Add a new field named "Quarter" with value "Start Q" in the "Value" field with 0 and Start Q + 1 in rows with "value" field having value 1. Blanks will not be there as we have filtered it out.
-- LEFT(), LEN(), MID(), VALUE() etc... are basic text handling functions used to generate the next quarter's value from a string like "FY2021Q1"

VAR Output2 = 
    ADDCOLUMNS(
        Output1,
        "Quarter",
        VAR V = [Value]
        VAR SQ = [Start Q]
        VAR NQ = 
            IF(
                VALUE(RIGHT(SQ,1))<4,
                LEFT(SQ,LEN(SQ)-1)&(value(RIGHT(SQ,1))+1),
                LEFT(SQ,2)&(VALUE(MID(SQ,3,4))+1)&"Q1"
                )
        VAR Q = 
            IF(V=0,SQ,NQ)
        RETURN
        Q
    )
-- Add a temporary field called "Revenue 2" and split the revenue between the quarters and the number of salespeople. The cardinality of each project in the table will tell us the denominator.
VAR Output3 =
    ADDCOLUMNS(
        Output2,
        "Revenue 2",
        VAR Proj = [Project]
        VAR ProjCount = COUNTROWS(FILTER(Output2,[Project]=Proj))
        VAR Rev = [Revenue]
        VAR Rev2 = DIVIDE(Rev,ProjCount,0)
        RETURN
        Rev2
    )
--Discard unnecesary fields and choose only relevant fields with correct field names.
VAR Result = 
    SELECTCOLUMNS(
        Output3,
        "Quarter",[Quarter],
        "Project",[Project],
        "Sales Person",[Sales Person],
        "Revenue",[Revenue 2]
    )
RETURN
-- Return the result.
Result



View solution in original post

2 REPLIES 2
Anonymous
Not applicable

Hey, I started off with the "Why not?" question and worked on it step by step, starting from your sample data in a table named "Existing Table". I have not thought about the right method, shortest method, optimized method, or anything like that. Just built the code step by step, but got the result.

Existing Table

sreenathv_0-1615279231446.png

Output

sreenathv_1-1615279267524.png


The DAX code for this calculated table is given below, it is quite large, but I have given comments in each step so that you will be able to understand what each step does.

ProjectTable = 
-- Get a list of projects
VAR ListOfProjects = ALLSELECTED(ExistingTable[Project],ExistingTable[Lead Time],ExistingTable[Revenue])
-- Crossjoin the list of projects with another table with one-column and two-rows that contains the list of 2 sales persons (the field name of the new table will be "Value")
VAR LOP_WS =
    GENERATE(
        ListOfProjects,
        VAR CP = [Project]
        VAR SP1 = LOOKUPVALUE(ExistingTable[Salesperson],ExistingTable[Project],CP)
        VAR SP2 = LOOKUPVALUE(ExistingTable[Secondary Salesperson],ExistingTable[Project],CP)
        VAR RN = IF(ISBLANK(SP2),BLANK(),2)
        VAR LOS = { {SP1},{SP2} }
        RETURN
        LOS
    )
-- Rename the "Value" field to "Sales Person" and also filter the blanks out.
VAR X = SELECTCOLUMNS(
FILTER(LOP_WS,[Value]<>""),
"Project",[Project],
"Revenue",[Revenue],
"Lead Time",[Lead Time],
"Sales Person",[Value]
)
--Add an additional row for all projects with more than 50 as the lead time. And an additional column to identify the extra rows. 
--The new field will have 3 values, 0 in the existing rows. 1 in the new field if the project has leadtime>=50, blank() in the new field if the project has <50 lead time.
VAR LOP_WS2 =
    GENERATE(
        X,
        VAR LT = IF([Lead Time]>=50,1,BLANK())
        VAR T = {{0},{LT}}
        return
        T
    )
--Filter out the blanks in the new field and also add the starting quarter of the project as "Start Q"
VAR Output1 = ADDCOLUMNS(FILTER(LOP_WS2,NOT(ISBLANK([Value]))),"Start Q",LOOKUPVALUE(ExistingTable[Quarter],ExistingTable[Project],[Project]))

-- Add a new field named "Quarter" with value "Start Q" in the "Value" field with 0 and Start Q + 1 in rows with "value" field having value 1. Blanks will not be there as we have filtered it out.
-- LEFT(), LEN(), MID(), VALUE() etc... are basic text handling functions used to generate the next quarter's value from a string like "FY2021Q1"

VAR Output2 = 
    ADDCOLUMNS(
        Output1,
        "Quarter",
        VAR V = [Value]
        VAR SQ = [Start Q]
        VAR NQ = 
            IF(
                VALUE(RIGHT(SQ,1))<4,
                LEFT(SQ,LEN(SQ)-1)&(value(RIGHT(SQ,1))+1),
                LEFT(SQ,2)&(VALUE(MID(SQ,3,4))+1)&"Q1"
                )
        VAR Q = 
            IF(V=0,SQ,NQ)
        RETURN
        Q
    )
-- Add a temporary field called "Revenue 2" and split the revenue between the quarters and the number of salespeople. The cardinality of each project in the table will tell us the denominator.
VAR Output3 =
    ADDCOLUMNS(
        Output2,
        "Revenue 2",
        VAR Proj = [Project]
        VAR ProjCount = COUNTROWS(FILTER(Output2,[Project]=Proj))
        VAR Rev = [Revenue]
        VAR Rev2 = DIVIDE(Rev,ProjCount,0)
        RETURN
        Rev2
    )
--Discard unnecesary fields and choose only relevant fields with correct field names.
VAR Result = 
    SELECTCOLUMNS(
        Output3,
        "Quarter",[Quarter],
        "Project",[Project],
        "Sales Person",[Sales Person],
        "Revenue",[Revenue 2]
    )
RETURN
-- Return the result.
Result



Hi there, 

 

Thank you so much for taking the time to help me solve this puzzle. I spent some time trying to understand the thought process behind your solution, and it worked magical. 🙂 

 

Before seeing your solution I wasn't even sure if this was possible. Thank you. 

Helpful resources

Announcements
Microsoft Fabric Learn Together

Microsoft Fabric Learn Together

Covering the world! 9:00-10:30 AM Sydney, 4:00-5:30 PM CET (Paris/Berlin), 7:00-8:30 PM Mexico City

PBI_APRIL_CAROUSEL1

Power BI Monthly Update - April 2024

Check out the April 2024 Power BI update to learn about new features.

April Fabric Community Update

Fabric Community Update - April 2024

Find out what's new and trending in the Fabric Community.