Row calculated from existing rows given some condition - powerbi

I'm really new to Power BI, I'm a data analyst and usually work with code, so I'm not really familiar with Excel like formulas
I have a table with like 20 columns, and I need only 2 columns for this calculation, so I'm going to zoom in the columns I need:
I want to add rows with Attribute5 for which is  Attribute1 - Attribute2 - Attribute3.
The result should look like this :
I'm really stuck with this since yesterday morning
I achieved it with a Measure by:
Creating a table containing distinct attributes :
TableXX = UNION(DISTINCT('Table'[Attributes]),{{"Attribute5"}})
Doing the calculating with a measure :
Measure =
SUMX (
DISTINCT ( 'Table 3'[Attributes] ),
SWITCH (
'Table 3'[Attributes],
"Attribute5", CALCULATE ( SUM ( 'Table'[Value] ), 'Table'[Attributes] = "Attribute1" )
- CALCULATE ( SUM ( 'Table'[Value] ), 'Table'[Attributes] = "Attribute2" )
- CALCULATE ( SUM ( 'Table'[Value] ), 'Table'[Attributes] = "Attribute3" ),
var a = 'Table 3'[Attributes] return
CALCULATE ( SUM ( 'Table'[Value] ),'Table'[Attributes]=a)
)
)
But I don't really want a measure, I want to replace Value Column by this measure, how can I achieve that?

You can define a new table as the union of the existing table and a calculated table that has the new rows that you want:
NewTable =
VAR Table5 =
SUMMARIZE (
FILTER (
'Table 3',
'Table 3'[Attributes] IN { "Attribute1", "Attribute2", "Attribute3" }
),
'Table 3'[Date],
"Attributes", "Attribute5",
"Value", SUMX (
'Table 3',
IF (
'Table 3'[Attributes] = "Attribute1",
'Table 3'[Value],
- 'Table 3'[Value]
)
)
)
RETURN
UNION ( 'Table 3', Table5 )
The new calculated table is stored in the variable Table5 which takes only the rows containing attributes 1, 2, or 3 and for each date takes the sum of the values where attributes other than 1 get a negative sign.

I would say that the easiest way is to pivot Values column, so you will get a table with columns Date, Attribute1, Attribute2, Attribute3 and Attribute4:
Then add a custom column Attribute5:
And then unpivot attributes columns to get the table back:

Related

PowerBI: How to get distinct count for a column in a table, while grouping for many columns separately

I have a table with multiple date columns, and a single label column, as shown by following code
Data = DATATABLE (
"Date1", DATETIME,
"Date2", DATETIME,
"Label", STRING,
{
{ "2020-01-01","2020-01-02", "A" },
{ "2020-01-01","2020-01-01", "A" },
{ "2020-01-01","2020-01-02", "B" },
{ "2020-01-01","2020-01-01", "D" },
{ "2020-01-01","2020-01-02", "E" },
{ "2020-01-02","2020-01-01", "A" },
{ "2020-01-02","2020-01-02", "B" },
{ "2020-01-02","2020-01-01", "C" }
}
)
I want to plot a chart of count of distinct labels for each day, when considering date1, as well as when considering date2. These need to be in same plot, as a clustered bar plot, as shown below. This means I need to get the values on a new date column.
The expected result looks like this,
Date | value1 | value2
---------------------------------
1/1/2020 12:00:00 AM | 4 | 3 |
1/2/2020 12:00:00 AM | 3 | 3 |
Current Solution:
I am creating two different tables for each of the counts, as follows
Date1_Count =
ADDCOLUMNS (
ALL ( Data[Date1] ),
"Count",
CALCULATE (
DISTINCTCOUNT ( Data[Label] )
)
)
and
Date2_Count =
ADDCOLUMNS (
ALL ( Data[Date2] ),
"Count",
CALCULATE (
DISTINCTCOUNT ( Data[Label] )
)
)
Then I create a third table with dates as such,
Final_Counts = CALENDAR("2020-01-01", "2020-01-04")
Next, I add relationship between the three dates, viz. Date1_Count table, Date2_Count table, and Final_Counts table
Finally, I combine the data using RELATED function as follows
value1 = RELATED(Date1_Count[Count])
value2 = RELATED(Date2_Count[Count])
Question
Is there a simpler solution that does not require creating one table per date column? The current method is not scalable to many date columns.
Assuming you only have a handful of date columns, you just need a single date dimension table and one measure per date column.
Define a date table to use on the x-axis (no relationships to other tables):
DimDate = CALENDAR("2020-01-01", "2020-01-04")
Then define measures that match the various date columns to the date table:
value1 =
CALCULATE (
DISTINCTCOUNT ( Data[Label] ),
Data[Date1] IN VALUES ( DimDate[Date] )
)
and
value2 =
CALCULATE (
DISTINCTCOUNT ( Data[Label] ),
Data[Date2] IN VALUES ( DimDate[Date] )
)
If you have more than a handful of DateN columns, then you'd probably be best served to reshape your data where you unpivot all those columns.
For just the two you have the data would look like
In this case, you use Unpivot[Column] as the Legend and only need a single measure:
value =
CALCULATE (
DISTINCTCOUNT ( Unpivot[Label] ),
Unpivot[Date] IN VALUES ( DimDate[Date] )
)
This gives a similar looking result:
It is possible to obtain the Final_Counts calculated table in one step, using ADDCOLUMNS to iterate over Data[Date1], and then calculating Value1 as the DISTINCTCOUNT over the Data table filtered on the currently iterated Date1.
This work thanks to the CALCULATE statement that triggers a context transition.
Obtaining the Value2 requires to create a new filter context over Date2 using the currently iterated Date1.
First we save the current Date1 in a variable to be used inside CALCULATE in the filter expression on Date2.
We also need REMOVEFILTERS( Data ) to remove the filter context over Date1 set by the context transition.
Final_Counts =
ADDCOLUMNS(
ALL( Data[Date1] ),
"Value1",
CALCULATE(
DISTINCTCOUNT( Data[Label] )
),
"Value2",
VAR CurrentDate = Data[Date1]
RETURN
CALCULATE(
DISTINCTCOUNT( Data[Label] ),
REMOVEFILTERS( Data ),
Data[Date2] = CurrentDate
)
)

DAX - TOPN() in a SUMX() for multiple transactions

I need your help.
I am trying to make a calculated column which sum the sales for the last two dates (there are not sales on all dates!) for each product.
I have tried to use the calculation:
CALCULATE (
SUMX ( TOPN ( 2; 'Table'; 'Table'[date_ID] ); 'Table'[Sale] );
ALLEXCEPT ( Table; 'Table'[Product_ID] )
)
But this only works if you have one sale per date per product ID.
What do I do if there are many transactions per date and prod ID?
Below I have a table where I have (filtered) one date and one product.
Now, I have made a calculated column that sums all transactions per date and product ID (for reference).
This is
Calculated Column 2 =
CALCULATE (
SUMX ( Table; Table[Sale] );
ALLEXCEPT ( Table; 'Table'[Date]; 'Table'[Product_ID] )
)
Now comes the difficult part.
If I want to sum the transactions for the last two dates on each product, I have made the following calculation:
Calculated Column 1 =
VAR SumProd =
CALCULATE (
SUMX ( Table; Table[Sale] );
ALLEXCEPT ( Table; Table[Date]; Table[Product_ID] )
)
RETURN
CALCULATE (
SUMX ( TOPN ( 2; 'Table'; 'Table'[Date] ); SumProd );
ALLEXCEPT ( Table; Table[Product_ID]; Table[Date] )
)
The Problems:
The calculations sums ALL the values in each category
Example: in the table, you see "Calculated column 1"=7571200, which is 27040 * number of transactions? I only want the value 27040.
For some reason, the TOPN() doesn’t work. If I change the N_Value=2 to N_Value=3, the calculation doesn’t change?
Please, does anyone know what is wrong with my calculation?
Thanks.
Br,
Jakob
In your measure, SumProd is a constant that you're summing for each row in the table. This is not what you want.
I'd suggest something more like this:
Calculated Column 1 =
VAR LastTwoDates =
CALCULATETABLE (
VALUES ( Table[Date] );
TOPN ( 2; ALLEXCEPT ( Table; Table[Product_ID] ); Table[Date] )
)
RETURN
CALCULATE (
SUM ( Table[Sale] );
ALLEXCEPT ( Table; Table[Product_ID] );
Table[Date] IN LastTwoDates
)
In this, we first calculate a list of the top 2 dates associated with Product_ID and store it as a variable. Then we use that as a filter when calculating the sum of Sale.
I'm not positive this exact syntax will work, but I hope it will point you in a better direction.
It turns out my code didn't work exactly as intended. Try this instead:
Calculated Column 1 =
VAR ProductDates =
CALCULATETABLE (
VALUES ( Table1[Date] );
ALLEXCEPT ( Table1; Table1[Product_ID] )
)
VAR LastTwoDates = TOPN ( 2; ProductDates; [Date] )
RETURN
CALCULATE (
SUM ( Table1[Sale] );
ALLEXCEPT ( Table1; Table1[Product_ID] );
Table1[Date] IN LastTwoDates
)

Is there Dax code to take the difference between 2 rows from a summarized table

I need to be able to get the difference between 2 successive rows in a Summarized table, by rank, so that I can then get the average of the differences of each row. And I can't create a new table as I need this DAX query to be filterable
I've been able to get this far, but do not know how to add a difference column that will show the DSOValue difference between rows 1-2, 2-3, 3-4 ...
ADDCOLUMNS (
SUMMARIZE (
Table1,
Table1[Date],
"DSOValue", DIVIDE ( SUM ( 'Table1'[AR] ) * 91.5, SUM ( 'Table1'[Sales] ), 0 )
),
"Rank", RANKX (
Table1,
CALCULATE (
COUNTROWS ( Table1),
FILTER ( Table1, Table1[Date] <= EARLIER ( Table1[Date] ) )
),,ASC,DENSE)
)
I've tried embedding this code within another ADDCOLUMNS function, but it won't let me CALCULATE and FILTER on my created columns (DSOValue and RANK)
you can use the following:
Diff = 'Table1'[ DSOValue ] - LOOKUPVALUE('Table1'[ DSOValue ]; 'Table1'[Date ];CALCULATE( MAX('Table1'[Date ]);FILTER('Table1';'Table1'[Date ]<EARLIER('Table1'[Date ]))))
Note: You cannot use <= here, it will pick its own date and all will be null. It would also be easier to add an index column, when you have this you can use Lookupvalue with Index -1

Pareto (80/20) Segmentation in Power BI

I created 80/20 segmentation in my Power BI data model and I got what I wanted (see the table below).
Now I want to calculate new Name column with the next logic: if Cumulative % <=80% show value from the "Customer Name" column, otherwise show "Other" (the result will be the column Name as in the table below).
I tried with this calculated column but it doesn't work (the result isn't correct, it's always "Other"):
80/20 Name = IF([Cumulative Percen.] <= 0.8, SalesReport[Names], "Other")
Note: "Cumulative Percen." is calculated measure.
How can I do this?
In the next step, I'll use a pie chart to show this segmentation where all customers with small cumulative transactions will be categorized as Other.
The calculated measures that I used:
Customer Rank by Transaction =
IF (
HASONEVALUE ( SalesReport[CustName] ),
RANKX (
ALLSELECTED ( SalesReport[CustName] ),
CALCULATE ( [# of Transactions] ),
,
DESC,
DENSE
)
)
Customer Cumulative Transaction =
VAR CurrentCustimerRank = [Customer Rank by Transaction]
RETURN
SUMX (
FILTER (
ALLSELECTED ( SalesReport[CustName] ),
CALCULATE ( [Customer Rank by Transaction] ) <= CurrentCustimerRank
),
CALCULATE ( DISTINCTCOUNT ( SalesReport[CustID] ) )
)
Customer Cumulative Transaction Percen. =
[Customer Cumulative Transaction]
/ CALCULATE (
DISTINCTCOUNT ( SalesReport[CustID] ),
ALLSELECTED ( SalesReport[CustName] )
)

How to find the last value ordered by a different column

I have a table MyTable has columns: QuoteID, ControlNo, Premium, ExpirationDate
I need to create a measure that would grab the SUM(Premium) and EffectiveDate should be <= Today() and last ExpirationDate (ordered by QuoteID DESC) should be >= Today().
How can I translate below statement to DAX?
In SQL, I would do this way:
select sum(Premium) as Premium
from MyTable t
where EffectiveDate <= GETDATE() and
(select top 1 t2.ExpirationDate
from MyTable t2
where t2.ControlNo = t.controlno
order by t.quoteid desc) >= GETDATE()
How can I write it in DAX?
I've tried this, but it's not working properly:
Premium =
CALCULATE (
SUM ( fact_Premium[Premium] ),
FILTER (
fact_Premium,
fact_Premium[EffectiveDate] <= TODAY () &&
TOPN ( 1, ALL ( fact_Premium[ExpirationDate] ),
fact_Premium[QuoteID], ASC ) >= TODAY ()
)
)
UPDATE:
Trying to create calculated table from fact_Premium dataset, but still not sure how can I filter it
In_Force Premium =
FILTER(
ADDCOLUMNS(
SUMMARIZE(
//Grouping necessary columns
fact_Premium,
fact_Premium[QuoteID],
fact_Premium[Division],
fact_Premium[Office],
dim_Company[CompanyGUID],
fact_Premium[LineGUID],
fact_Premium[ProducerGUID],
fact_Premium[StateID],
fact_Premium[ExpirationDate]
),
"Premium", CALCULATE(
SUM(fact_Premium[Premium])
),
"ControlNo", CALCULATE(
DISTINCTCOUNT(fact_Premium[ControlNo])
)
), // Here I need to make sure TODAY() falls between fact_Premium[EffectiveDate] and (SELECT TOP 1 fact_Premium[ExpirationDate] ORDE BY QuoteID DESC)
)
There's a couple of problems with the DAX here.
First, when you use TOPN, your ordering expression (3rd argument) can only reference rows in the table you are operating on (2nd argument), so only using the [ExpirationDate] column there won't work. I think you probably want fact_Premium instead of ALL ( fact_Premium[ExpirationDate] ).
Second, the TOPN function returns a table rather than a single value, so you need to access the column you want somehow. One option would be to use an iterator like SUMX or MAXX:
MAXX( TOPN(...), fact_Premium[ExpirationDate] )
You could also use SELECTCOLUMNS which will coerce a single row, single column table to just be a value:
SELECTCOLUMNS( TOPN(...), "ExpirationDate", fact_Premium[ExpirationDate] )
I can't guarantee that this will work perfectly, but it should get you closer to your goal:
Premium =
CALCULATE (
SUM ( fact_Premium[Premium] ),
FILTER (
fact_Premium,
fact_Premium[EffectiveDate] <= TODAY () &&
SUMX( TOPN ( 1, fact_Premium, fact_Premium[QuoteID], DESC ),
fact_Premium[ExpirationDate] )
>= TODAY ()
)
)