The following measure works, but rather than making separate measures for each year, I want to use a variable in place of 2022.
Q1FY22 Cost = CALCULATE(
SUM('Invoice Amounts'[CLIN Total]),'Calendar'[Fiscal Year]=2022,'Calendar'[Fiscal Quarter]=1)
I created another measure,
ThisFY=2022
When I substitute in the original,
Q1FY22 Cost = CALCULATE(
SUM('Invoice Amounts'[CLIN Total]),'Calendar'[Fiscal Year]=[ThisFY],'Calendar'[Fiscal Quarter]=1)
I receive the error: A function 'PLACEHOLDER' has been used in a True/False expression that is used as a table filter expression. This is not allowed.
This is a lineage issue.
Try this.
Q1FY22 Cost = CALCULATE(
SUM('Invoice Amounts'[CLIN Total]), TREATAS( {[ThisFY]}, 'Calendar'[Fiscal Year]),'Calendar'[Fiscal Quarter]=1)
Related
This is my first stack overflow question so please forgive me if I haven't followed best practices/formatting for this forum.
I am trying to use DAX to write some unit tests for my powerBi reports however I'm struggling to make my tests both dynamic whilst testing against verified historic data.
The problem comes from the fact that many of the measures I would like to test have a date related measure and/or function nested inside for example:
Yesterday's amount = CALCULATE(SUM('Cost Analysis'[computedAmount]),('Cost Analysis (New)'[timeUsageStarted] = TODAY() - 1))
I would like my test to be able to dynamically test [yesterday's amount] (even if somebody changed some of the measure logic) however I need to hard code a date in place of the TODAY() function in order to test it against an expected value that I have access too.
I have been able to rewrite the measure logic (adding a company filter and rounding in the process) with a hard coded date for my expected value but this means changes made to the measure would make my test obsolete.
EVALUATE
ADDCOLUMNS(
UNION(
ROW(
"Test Name", "Testing [Yesterday's Amount] where yesterday is set to 20/03/22"
,"Expected Value"
, 48.81
,"Actual Value"
,ROUND(CALCULATE(SUM('Cost Analysis (New)'[computedAmount]), 'Cost Analysis (New)'[Companies] = "company name",
FILTER(ALL('Cost Analysis (New)'),
'Cost Analysis (New)'[timeUsageStarted] = DATE(2022, 03, 20)
)
) ,2
),"Test Failed", IF([Expected Value] <> [Actual Value], "Yes", BLANK())
)`
on the other side I can make my expected value equal to the output of [Yesterday's amount] however I then don't have control over the value of TODAY() so my expected value would need to be changed every day (which is of course not useful).
Is there a way that I could make my expected value = [Yesterday's amount] instead of my hardcoded rewrite whilst passing in a value to hard code the value for TODAY()?
I have the same problem with nested date measures such as [current month] being part of a [month to date spend] calculation.
INTRO
I realize the title makes the problem sound simple, however, this task has proved incredibly difficult for me and it's taken up hours of my time every day for the past week. With that being said, any help is appreciated!
The first table involved is LoadView, which contains the fields LoadNumber, CarrierID, and BookedFrom. The second table is LoadBaseView, which contains the fields LoadNumber, CarrierID, and BookedOnDateTime. These two are related by LoadNumber.
The visualization I wanna add to is the following, where the new row would be "New Carriers" listed right under "Carriers":
Lastly, preliminary info wise, that table is just a matrix with LoadView[BookedFrom] as the only context (Autobook, etc.) and simple measures across LoadView along with it.
PROBLEM
Now that I've (hopefully) laid everything out clearly, let me explain exactly what I am looking for. I would like to count the amount of new carriers that have booked in each BookedFrom category, i.e. I would like to count the amount of carriers booking that have never booked before for each category. This means that any carrier could potentially be counted in each BookedFrom column, just to clarify. I've tried many different measure to capture this and I've run into a whole host of problems, including memory insufficiencies to exceeding available resources. The latter's DAX is the following:
IsFirstCarrierBookedFrom* =
Var current_booked_from = MIN(dsgLoadView[BookedFrom])
Var T1 = ADDCOLUMNS(ALL(dsgLoadView),"BookedOnDateTime",RELATED(dsgLoadBaseView[BookedOnDateTime]))
Var T2 = GROUPBY(T1,dsgLoadView[CarrierId],dsgLoadView[BookedOn],"MinBookedOnDateTime",MINX(CURRENTGROUP(),[BookedOnDateTime]))
Var T3 = NATURALINNERJOIN(T1,T2)
Var T4 = FILTER(T3,[BookedOnDateTime]=[MinBookedOnDateTime])
RETURN
CALCULATE(DISTINCTCOUNT([CarrierId]),FILTER(T4,[BookedFrom]=current_booked_from),USERELATIONSHIP(dsgLoadView[BookedOnDate],dsgCalendar[Date]))
The above results in this error:
This next attempt results in a memory insufficiency error:
TotalFirstCarrierBooks* =
Var current_row_carrier_id = MIN(dsgLoadBaseView[CarrierId])
Var current_row_booked_from = MIN(dsgLoadView[BookedFrom])
Var first_booked_from_date_time =
CALCULATE(
MIN(dsgLoadBaseView[BookedOnDateTime]),
FILTER(
ALL(dsgLoadBaseView),
dsgLoadBaseView[CarrierId]=current_row_carrier_id
),
FILTER(
All(dsgLoadView),
dsgLoadView[BookedFrom]=current_row_booked_from
)
)
Var is_first_date = IF(first_booked_from_date_time=MIN(dsgLoadBaseView[BookedOnDateTime]),1,0)
RETURN
SUMX(dsgLoadBaseView,is_first_date)
With that being said, if I take out the BookedFrom bits (current_row_booked_from, etc.) the measure works and when alongside LoadNumber it returns a 1 or 0, denoting that the LoadNumber was or was not the first booking by the Carrier. I decided this wasn't the right path, though, due to that memory error. Also, summing up these 1's gets me duplicate bookings per Carrier per BookedFrom. In other words, a Carrier can book 2 loads via Manual at the same DateTime and, as those 2 rows would have 1's per the logic, that would add up to 2 which is a no-no.
THANK YOU
Seriously, to anyone who got this far! This problem has eaten up a ton of time for me, I've Googled relentlessly and I've watched countless YouTube videos. Thanks for your time!
I unable to provide a solution that would work because I don't have the data and its impossible to solve questions like these without the actual data, but I do know DAX so based on my experience here are my suggestions.
For measure IsFirstCarrierBookedFrom:
Substitute DISTINCTCOUNT with SUMX ( VALUES ( Table[CarriedID] ), 1 ) and see if that resulst in better performance
You are adding a column to dsgLoadView with RELATED, what is the cardinality of this table? Pay attention to these details and based on that supply a smaller table to ADDCOLUMNS and then use CALCULATE to compute BookedOnDateTime
Functions like NATURALINNERJOIN utilize the slower engine of DAX
You are probably applying a huge table T4 into the filter context with CALCULATE
For measure TotalFirstCarrierBooks:
You are probably iterating a huge tabls inside CALCULATE in the variable first_booked_from_date_time, try to change that to this:
VAR first_booked_from_date_time =
CALCULATE (
MIN ( dsgLoadBaseView[BookedOnDateTime] ),
dsgLoadBaseView[CarrierId] = current_row_carrier_id,
dsgLoadView[BookedFrom] = current_row_booked_from,
REMOVEFILTERS ( dsgLoadBaseView ),
REMOVEFILTERS ( dsgLoadView )
)
The RETURN part isn't working how you would expect it to, variables in DAX are constants, before RETURN the value of is_first_date is computed and is now a fixed value, nothing can change it, let's assume it is 10 then inside SUMX ( dsgLoadBaseView, is_first_date ) you are summing 10 for each row of the table dsgLoadBaseView
Given the following data model:
I need to build a report that will display the following attributes:
As you see, I need to provide an attribute from the SalesOrder table [InternDocumentNumber[, so the visual will have grain on the order level.
Now, the problem is with measure [first order date v1] that should calculate the first order date made by the customer and display this value for all different orders from the same customer.
So far, I build the following measure
first order date v1 = CALCULATE (
FIRSTDATE( SalesOrderDate[SalesOrderDate]),
USERELATIONSHIP( SalesOrder[OrderDate], SalesOrderDate[SalesOrderDate]),
CROSSFILTER ( SalesOrder[OrderDate], SalesOrderDate[SalesOrderDate],both ),
ALL(SalesOrder)
)
However, this measure calculates forever, ending with the error:
Could you please advise me on how to write this measure, so it will perform better?
EDIT
Let me use an example from DAX.DO to be more clear on what I would like to get. Below is a screen of query and the result
What I would like to achieve is a measure, that will show me the min date for order on a customer level, and not the order level, as it is now. In other words, values in the red rectangle should be the same for customer 6, regardless of the grain of the table. Is this possible in DAX at all?
Reference to DAX.DO snippet:
https://dax.do/wxU6NNRHrencrg/
EDIT 2
Actually, I am able now to design a measure that solves the problem, however it performs very bad (timeouts in the end)
Here is the code screen and the DAX.DO reference
https://dax.do/wxU6NNRHrencrg/
You can try this:
CALCULATE (
MIN ( Sales[Order Date] ),
ALLEXCEPT ( Sales, Customer[CustomerKey] )
)
Using DAX to identify first instance of a record
I'm faced with trying to identify the first instance in a database where someone (identified by the ID column) has purchased a product for the first time. It's possible for said person to purchase the product multiple times on different days, or purchase different products on the same day. I drummed up an excel formula that gets me there, but am having trouble translating into DAX.
=COUNTIFS(ID,ID,PurchaseDate,"<="&PurchaseDate,Product,Product)
Which results in the correct values in the "First Instance?" Column.
Ideally I won't have to hardcode values, as I would like to use the "Product" column as a parameter in the future. If there are other suggests aside from translating this in DAX, that would also be appreciated! (IE using filters, or other tools in PowerBI)
Thanks in advance!
This is very similar to an answer I gave to another question (which you can find here).
In that question, the request was to see a running count of rows for the given row's criteria (product, year, etc.). We can modify that slightly to get it to work in your problem.
This is the formula I provided in the answer I linked above. The basic concept is to use the EARLIER functions to get the value from the row and pass it into the filter statement.
Running Count =
COUNTROWS(
FILTER(
'Data',
[ProductName] = EARLIER([ProductName]) &&
[Customer] = EARLIER([Customer]) &&
[Seller] = EARLIER([Seller]) &&
[Year] <= EARLIER([Year])
)
)
What I would suggest for your problem is to create this as a TRUE/FALSE flag by simply checking if the running count is 1. This formula will evaluate to a Boolean flag.
First Instance =
COUNTROWS(
FILTER(
'Data',
[ID] = EARLIER([ID]) &&
[Product] = EARLIER([Product]) &&
[Purchase Date] <= EARLIER([Purchase Date])
)
) = 1
I’m trying to compute the difference between (budget) allocations and expenditures.
At first glance, this seems easy to do with a simple measure:
Balance = SUM(Register[AllocationAmount]) – SUM(Register[TransactionAmount])
However, there’s an extra rule to factor in: Transaction amounts dated prior to the first allocation should be ignored. Measure Balance gets more complex to accommodate this:
Balance = CALCULATE(
SUM(Register[AllocationAmount]) - SUM(Register[TransactionAmount]),
FILTER(Dates,
Dates[Date] >= FIRSTDATE(Category[InitialAllocationDate])
&& NOT ISBLANK(FIRSTDATE(Category[InitialAllocationDate]))
)
)
Unfortunately, Balance doesn't add up correctly when used to compute totals up a hierarchy in the Category table. This makes sense. When Balance is evaluated up the hierarchy, FIRSTDATE(Category[InitialAllocationDate]) in the date filter pulls the first date out of all dates associated with all Category rows in context at that higher level and then uses this date to apply the filter once for the entire grouping.
This is incorrect. In order to produce an accurate total, the filter needs to be applied on a per-Category basis so that filtering factors in each category's InitialAllocationDate. To achieve this, I changed Balance so that it computes only when a single Category[Name] filter is applied (i.e. no hierarchy grouping is taking place). Then, I created a separate measure that uses SUMX to evaluate Balance on a per-Category row basis.
Balance = IF (HASONEFILTER(Category[Name])),
CALCULATE(
SUM(Register[AllocationAmount]) - SUM(Register[TransactionAmount]),
FILTER(Dates,
Dates[Date] >= FIRSTDATE(Category[InitialAllocationDate])
&& NOT ISBLANK(FIRSTDATE(Category[InitialAllocationDate]))
)
)
)
CumulativeBalance = SUMX(Grouping, Register[Balance])
This produces correct totals up Category's hierarchy (yay!); however, it requires two measures.
Question
Is there a way I can eliminate the second measure (CumulativeBalance) and instead somehow adjust Balance so that it computes correctly up the hierarchy?