Dax -- Dividing by aggregates from two different facts - powerbi

I am trying to convert a piece of SQL to dax.
It only involves two tables, both facts and a common dimension attribute, Encounter.
I want to sum all charges by encounter and sum collections by encounter, filtered to only collections of TransactionRollup_Name = Contractual, TransactionTypeDescription = Adjustment, posted last month.
I will filter the System and Action <> Delete in the reporting client (powerbi or excel)
Once these are obtained I want the sum of contractual collections where the portion of contractual collections over total encounter charges is >= .9 and < 1
SQL:
DECLARE #startdate INT = 20181201
, #thrudate INT = 20181231
, #systemcode VARCHAR(1) = '1';
SELECT SUM(coll.Contractual)
FROM ( SELECT SUM(Amount) * -1 Contractual
, col.EncounterID
FROM
dwo.FactCollections col
JOIN dwo.DimTransactionCode_mds mds ON col.mds_TransactionID = mds.SK_TransactionKey
WHERE
mds.TransactionRollup_Name = 'Contractual'
AND mds.TransactionTypeDescription = 'Adjustment'
AND col.SystemID = TRY_CONVERT(INT, #systemcode)
AND col.Action <> 'Delete'
AND col.PostDateTime >= #startdate
AND col.PostDateTime <= #thrudate
GROUP BY col.EncounterID ) coll
JOIN ( SELECT EncounterID
, SUM(Amount) Charge
FROM dwo.FactCharges ldg
WHERE
ldg.SystemID = TRY_CONVERT(INT, #systemcode)
AND ldg.Action <> 'Delete'
GROUP BY ldg.EncounterID ) chg ON chg.EncounterID = coll.EncounterID
WHERE
chg.Charge <> 0
AND chg.Charge IS NOT NULL
AND coll.Contractual / chg.Charge >= .90
AND coll.Contractual / chg.Charge < 1.0;
Attempted Dax Measure:
90%-99.99% of Charges :=
CALCULATE (
'MeasureTable'[Sum of Contractual Adjustments],
FILTER (
'FactCollections',
DIVIDE (
'MeasureTable'[Sum of Contractual Adjustments],
'MeasureTable'[ChargeTotal]
)
>= .90
&& DIVIDE (
'MeasureTable'[Sum of Contractual Adjustments],
'MeasureTable'[ChargeTotal]
)
< 1.0
)
)
Charge := SUM ( 'FactCharges'[Amount] )
Sum of Contractual Adjustments :=
CALCULATE (
SUM ( FactCollections[Amount] ) * ( -1 ),
FILTER (
'Transaction Code',
'Transaction Code'[TransactionTypeDescription] = "Adjustment"
&& 'Transaction Code'[TransactionRollup_Name] = "Contractual"
)
)
Sample data on one encounter, per request.
Addendum
Going a different route with the dax, this gets me 1/2 way.
The summarizecolumns query gets me a result set that aggregates both charges and contractual collections up to the encounter and calculates the ratio of contractuals / charges.
The end result would need to filter this intermediate result set where
contractual / charge ratio is >= .9 and < 1
post dates for contractual collections should be filtered by reporting client filter context
All post dates for charges should be included, regardless of the post date filter context in the reporting client
I have no idea how to do that second part in dax though.
> EVALUATE SUMMARIZECOLUMNS (
> 'Encounter'[Encounter],
> "ChargeAmount", SUMX ( 'FactCharges', 'FactCharges'[Sum Charge Amount] ),
> "ContractualAmount", SUMX (
> 'FactCollections',
> CALCULATE (
> 'FactCollections'[Sum of Adjustments],
> 'Transaction Code'[TransactionRollup_Name] = "Contractual"
> )
> ),
> "Contractual : Charge", DIVIDE (
> SUMX (
> 'FactCollections',
> CALCULATE (
> 'FactCollections'[Sum of Adjustments] * -1,
> 'Transaction Code'[TransactionRollup_Name] = "Contractual"
> )
> ),
> SUMX ( 'FactCharges', 'FactCharges'[Sum Charge Amount] )
> ) )

Related

Create measure to calculate rows based on TO and FROM figures in another table

I have a report that fetches weekly data. I have a weeks table that contains the weeks and dates and relationships set up with the below tables.
I have a QueueSummary table;
I have ConciergeHours table;
The concierge hours differ from day to day, so i keep the start and finish time in a table so we can update it dynamically.
I am trying to create a measure to calculate how many interactions we have had, between the hours in the ConciergeHours table. Keep in mind this is a weekly report, so on any given day during the week, the hours may be different.
The calculation we are after is;
Number interactions accepted on queue LinkConciergeVQ (QueueSummary table) between the starthour and endhour in ConciergeHours table MINUS Number interactions offered on queue LinkVQ (QueueSummary table) between the starthour and endhour in ConciergeHours table
I currently have the measure looking like this. It works, but the between hours are not respected correctly, which i understand would be a result of the MIN, MAX.
m_deflections =
CALCULATE (
SUM ( QueueSummary[s_accepted] ),
QueueSummary[queue] = "LinkConciergeVQ",
filter(QueueSummary, [hour] >= min(ConciergeHours[starthour])),
filter(QueueSummary, [hour] < max(ConciergeHours[endhour]))
)
- CALCULATE (
SUM ( QueueSummary[s_offered] ),
QueueSummary[queue] = "LinkVQ",
filter(QueueSummary, [hour] >= min(ConciergeHours[starthour])),
filter(QueueSummary, [hour] < max(ConciergeHours[endhour]))
)
I hope i've explained this correctly.
If anyone could offer any help!?
Thanks so much
Not sure I understand your table relationships, but if its 1:* from ConciergeHours to QueueSummary via date then I think you can use this measure, or at least it puts you on the right track, I hope:
m_deflections =
var s_accept =
SUMX(
'ConciergeHours',
var startH = 'ConciergeHours'[startHour]
var endH = 'ConciergeHours'[endHour]
return
CALCULATE(
SUM('QueueSummary'[s_accepted]),
'QueueSummary'[hour] >= startH && 'QueueSummary'[hour] < endH
)
)
var s_offered =
SUMX(
'ConciergeHours',
var startH = 'ConciergeHours'[startHour]
var endH = 'ConciergeHours'[endHour]
return
CALCULATE(
SUM('QueueSummary'[s_offered]),
'QueueSummary'[hour] >= startH && 'QueueSummary'[hour] < endH
)
)
return
s_accepted - s_offered
I would collapse the 2 pairs of FILTER functions into a single FILTER for each CALCULATE. That will apply the filters against starthour and endhour in combination (the && means AND), where I expect they are currently applying as OR logic so not having any effect.
Along the lines of this:
m_deflections =
CALCULATE (
SUM ( QueueSummary[s_accepted] ),
QueueSummary[queue] = "LinkConciergeVQ",
FILTER (
QueueSummary,
[hour] >= MIN ( ConciergeHours[starthour] )
&& [hour] < MAX ( ConciergeHours[endhour] )
)
)
- CALCULATE (
SUM ( QueueSummary[s_offered] ),
QueueSummary[queue] = "LinkVQ",
FILTER (
QueueSummary,
[hour] >= MIN ( ConciergeHours[starthour] )
&& [hour] < MAX ( ConciergeHours[endhour] )
)
)

I will like a script in power bi that will calculate percentage increase or decrease from one month to the previous month

I want to display percentage increase or decrease in total for each month as I select each month i.e when I click on FEB, it should tell me whether there was a percentage increase/decrease in expenses compared to JAN.
I have tried different codes but keep getting an error message.
Here is a DAX CODE I tried:
change perc =
VAR ValueLastMONTH =
CALCULATE (
SUM ( population[TOTAL] ),
FILTER (
population,
population[MONTH]
= ( EARLIER ( population[MONTH] ) - 1 )
&& population[CATEGORY] = EARLIER ( population[CATEGORY] )
)
)
RETURN
IF (
ISBLANK ( ValueLastMONTH ),
0,
( population[TOTAL] - ValueLastMONTH )
/ ValueLastMONTH
I want a new column created to display the percentage increase or decrease from a month to its previous month.
Here is a screenshot of the excel document:
The Column 'Month' is not of type date. How would PowerBi know the text APR represents April? You need to make this column a date.
Now you need to change the script to work with DateDiff:
change perc =
VAR ValueLastMONTH =
CALCULATE (
SUM ( population[TOTAL] ),
FILTER (
population,
DATEDIFF(population[MONTH], EARLIER ( population[MONTH] ),MONTH) = 1
&& population[CATEGORY] = EARLIER ( population[CATEGORY] )
)
)
RETURN
IF (
ISBLANK ( ValueLastMONTH );
0;
( population[TOTAL] - ValueLastMONTH )
/ ValueLastMONTH)

Calculate Column Sum of a Generated Table - DAX

I've been trying to get the sum of the following table's column VALUE using DaxStudio in order to put that on PowerBI once is's ok, since PBI can get slow if you test a code for large calculated tables.
Table from DaxStudio
BU VALUE
------------------------
FOODS 0.0000
FIBI 0.0000
GEOS/CIS 0.7300
CASC
S_S
SGS
COCOA
COCOA/SSSA
CORPORATE
N/A
CIS
The code behind it:
DEFINE
VAR TOTAL =
CALCULATE (
SUMX (
PACKAGING_POWERBI_YEARLY_2;
PACKAGING_POWERBI_YEARLY_2[QUANTIDADE_ANTERIOR]
);
FILTER (
PACKAGING_POWERBI_YEARLY_2;
PACKAGING_POWERBI_YEARLY_2[DATE] = "2018"
&& PACKAGING_POWERBI_YEARLY_2[CODIGO] = "43130"
)
)
EVALUATE
SUMMARIZE (
CALCULATETABLE (
FILTER (
PACKAGING_POWERBI_YEARLY_2;
PACKAGING_POWERBI_YEARLY_2[PRECO_PONDERADO] <> BLANK ()
&& PACKAGING_POWERBI_YEARLY_2[PRECO_PONDERADO] <> 0
)
);
PACKAGING_POWERBI_YEARLY_2[BU];
"VALUE"; FORMAT (
(
CALCULATE (
SUMX (
PACKAGING_POWERBI_YEARLY_2;
PACKAGING_POWERBI_YEARLY_2[QUANTIDADE_ANTERIOR]
);
FILTER (
PACKAGING_POWERBI_YEARLY_2;
PACKAGING_POWERBI_YEARLY_2[DATE] = "2018"
&& PACKAGING_POWERBI_YEARLY_2[CODIGO] = "43130"
&& PACKAGING_POWERBI_YEARLY_2[PRECO_PONDERADO] <> BLANK ()
)
) / TOTAL
)
* (
CALCULATE (
SUMX ( PACKAGING_POWERBI_YEARLY_2; PACKAGING_POWERBI_YEARLY_2[PRECO_PONDERADO] );
FILTER (
PACKAGING_POWERBI_YEARLY_2;
PACKAGING_POWERBI_YEARLY_2[DATE] = "2018"
&& PACKAGING_POWERBI_YEARLY_2[CODIGO] = "43130"
&& PACKAGING_POWERBI_YEARLY_2[PRECO_PONDERADO] <> BLANK ()
)
)
);
"0.0000"
)
)
Instead of generating the table I would like to sum the results of column VALUE, but the only way I got to plot a result without error is through a "CALCULATED TABLE" (above).
Every filter I try leads to an error.
The idea is to get just the sum of that calculated column VALUE:
0.7300
But every simpler filter or SUMX condition I try, an error pops-up.
I'd think you could clean it up to look something like this:
CALCULATE (
SUMX (
VALUES ( PACKAGING_POWERBI_YEARLY_2[BU] ),
SUM ( PACKAGING_POWERBI_YEARLY_2[QUANTIDADE_ANTERIOR] )
/ CALCULATE (
SUM ( PACKAGING_POWERBI_YEARLY_2[QUANTIDADE_ANTERIOR] ),
ALL ( PACKAGING_POWERBI_YEARLY_2[BU] )
)
* SUM ( PACKAGING_POWERBI_YEARLY_2[PRECO_PONDERADO] )
),
FILTER (
PACKAGING_POWERBI_YEARLY_2,
PACKAGING_POWERBI_YEARLY_2[DATE] = "2018"
&& PACKAGING_POWERBI_YEARLY_2[CODIGO] = "43130"
&& PACKAGING_POWERBI_YEARLY_2[PRECO_PONDERADO] <> BLANK ()
&& PACKAGING_POWERBI_YEARLY_2[PRECO_PONDERADO] <> 0
)
)
This uses SUMX to iterate through each of the BU values and for each one, calculates the value
(QUANTIDADE_ANTERIOR / Total QUANTIDADE_ANTERIOR ) * PRECO_PONDERADO
where the filters are reused instead of repeated.
I can't guarantee that this code works exactly as intended, but it should point you in a better direction.

Project revenue calculation in DAX

I need to calculate the ongoing revenue for installation + maintenance for projects and calculate the monthly revenue for controlling purposes in DAX in Power BI.
The problem is the following.
The projects are stored in a table CONTRACTS like this:
And I have a separate date table INST_DATE_TABLE:
The tables are connected via the [INSTALLATION_DATE] field.
For every month the revenue is the total of the [INSTALLATION_REVENUE] if the installation was carried out that month plus from the first month on the monthly maintenance revenue which is given as the [MAINTENANCE_COST_PER_UNIT] * [MAINTENANCE_UNIT] / 12.
And the maintenance revenue should be only calculated if the current date is beyond the installation date!
Some contracts are not yet signed, so they dont't have an installation date set (NULL)
So the INSTALLATION REVENUE DAX is like this:
.INSTALLATION_REVENUE =
CALCULATE (
SUMX(CONTRACTS;
CONTRACTS[INSTALLATION_REVENUE]
);
CONTRACTS[INSTALLATION_DATE] > 0
)
And the MONTHLY REGULAR REVENUE is like this:
.REGULAR_REVENUE =
CALCULATE (
SUMX(CONTRACTS;
CONTRACTS[MAINTENANCE_COST_PER_UNIT]*CONTRACTS[MAINTENANCE_UNIT]
) / 12;
CONTRACTS[INSTALLATION_DATE] > 0
)
For all dates I can calculate the cash flow of the latter like this:
.REGULAR_REVENUE_ONGOING =
CALCULATE (
[.REGULAR_REVENUE];
ALL(INST_DATE_TABLE[INSTALLATION_DATE])
)
which gives me a nice series of monthly revenues for all periods. But I only would like to see this for the periods that are beyond the installation date!
So lets say filtered on contract 1 I have now the following cash flow:
But for periods before 2019.04.01 I would like to see zeros!
How can I do that?
I just can't filter on dates referring to the installation date of the project!
After I have the expected result for one contract it would be easy to sum it up for all contracts like this
.TOTAL_REVENUE =
[.INSTALLATION_REVENUE] + [.REGULAR_REVENUE_EXPECTED]
UPDATE:
I created a cumulative total to display the ongoing revenue as such:
.REGULAR_REVENUE_ONGOING =
CALCULATE (
[.REGULAR_REVENUE];
FILTER(
ALL(INST_DATE_TABLE[INSTALLATION_DATE]);
INST_DATE_TABLE[INSTALLATION_DATE
<=MAX(INST_DATE_TABLE[INSTALLATION_DATE])
)
)
this displays the correct series, but now I have another problem. When I try to cumulate this already cumulative data series it does not add up as a cumulative data series!
Any help would be appreciated
.REVENUE_TOTAL_CUMULATIVE =
CALCULATE(
[.REVENUE_TOTAL];
FILTER(
INST_DATE_TABLE;
INST_DATE_TABLE[INSTALLATION_DATE] <= MAX(INST_DATE_TABLE[INSTALLATION_DATE])
)
)
Assuming there are no end dates to your ongoing revenue, then try:
.REGULAR_REVENUE_ONGOING =
VAR DateMin =
CALCULATE(
MIN ( CONTRACTS[INSTALLATION_DATE] ),
ALL ( INST_DATE_TABLE )
)
VAR DateMax =
MAX ( INST_DATE_TABLE[INSTALLATION_DATE] )
RETURN
SUMX (
FILTER (
ALL ( INST_DATE_TABLE ),
INST_DATE_TABLE[INSTALLATION_DATE] >= DateMin && INST_DATE_TABLE[INSTALLATION_DATE] <= DateMax
),
[.REGULAR_REVENUE]
)
And for a cumulative total revenue:
.REVENUE_TOTAL_CUMULATIVE =
VAR DateCurrent = MAX ( INST_DATE_TABLE[INSTALLATION_DATE] )
VAR CumulativeInstallationRevenue =
CALCULATE (
[.INSTALLATION_REVENUE],
FILTER (
ALL ( INST_DATE_TABLE ),
INST_DATE_TABLE[INSTALLATION_DATE] <= DateCurrent
)
)
VAR CumulativeOngoingRevenue =
SUMX (
FILTER (
ALL ( INST_DATE_TABLE ),
INST_DATE_TABLE[INSTALLATION_DATE] <= DateCurrent
),
[.REGULAR_REVENUE_ONGOING]
)
RETURN
CumulativeInstallationRevenue + CumulativeOngoingRevenue
See https://pwrbi.com/so_55808659/ for worked example PBIX file

DAX using IF and AND functions

I'm trying to create a trending table with a value and a forecast. The forecast needs to start from the current month going forward. I am using this dax function:
Spend Forecast =
IF (
OR (
DIVIDE (
CALCULATE (
SUM ( refv_Spend_Cap[Spend_2019] ),
FILTER ( refv_Spend_Cap, refv_Spend_Cap[Split] = "Spend Actual" )
),
1000000
)
< 1,
DIVIDE (
CALCULATE (
SUM ( refv_Spend_Cap[Spend_2019] ),
FILTER ( refv_Spend_Cap, refv_Spend_Cap[Ind_Monthend] = "x" )
),
1000000
)
< 1
),
DIVIDE (
CALCULATE (
SUM ( refv_Spend_Cap[Spend_2019] ),
FILTER ( refv_Spend_Cap, refv_Spend_Cap[Split] = "Spend Forecast" )
),
1000000
),
""
)
The formula is calculating to check if these two conditions are met:
if there's no value then populate the forecast or if the ind monthend = 'x' then it should populate, if those two conditions are not met then it should leave it blank.
There are no syntax errors on the query but i am getting this error:
The True/False expression does not specify a column. Each True/False
expressions used as a table filter expression must refer to exactly
one column
Where did I go wrong?
It's very hard to comprehend such long formulas. It's the best practice to break them down into multiple measures. For example, your code can be re-writen as follows:
Create base measure:
Total Spend = SUM ( refv_Spend_Cap[Spend_2019] ) / 1000000
Now re-use the base measure to create 3 conditional measures. No need to use FILTER here:
Spend Actual = CALCULATE ( [Total Spend], refv_Spend_Cap[Split] = "Spend Actual" )
Spend X = CALCULATE ( [Total Spend], refv_Spend_Cap[Ind_Monthend] = "x" )
Spend Forecast = CALCULATE ( [Total Spend], refv_Spend_Cap[Split] = "Spend Forecast" )
Then the final result is simply:
Forecast = IF ( [Spend Actual] < 1 || [Spend X] < 1, [Spend Forecast], "")
It's much easire to understand what's happening, and easier to debug. You will also gain perfomance bonus because (usually) re-used measures are cached and calculated only once.
Try this code, if it still gives you problems, describe the new error and I'll help you fix it.
BTW, there is a popular free tool to format your DAX code:
Dax Formatter