Can I dynamically derive Dax Filters from "dissecting"a criteria field in my database? - powerbi

I have a database table that contains records, where each record has a criteria attribute. This criteria attribute can hold anywhere between 1-n criteria that I'd like to apply as filters on a different table.
This looks something like:
message.status:::eq:::submitted;;;message.count:::ge:::5
but could also be only
message.count:::ge:::5
What I'd like to do in DAX, is take that string and translate it into dynamic Filter attributes. So I somehow need to split the string based on ;;;, and then disect each section into the target (e.g. message[count]), the operator (e.g. ge --> >=) and the value (e.g. 5).
So in the end the following DAX snippet should be added to my Calculate 1 or more times:
example measure = CALCULATE(
COUNTROWS('message),
FILTER (
ALL('message'),
--- line below should be dynamically injected
message[count] >= 5
),
I'm struggling with how to create a loop (is this even possible in PBI?), and then even with a single string... hoe to filter based on this.
Thanks

You can try to build new table for splited message.
Table 2 =
var _splitby = ";;;"
var _string = SELECTCOLUMNS(ADDCOLUMNS(VALUES('Table'[message]),"pathx", SUBSTITUTE([message],_splitby,"|")),"pathx",[pathx])
var _generate = GENERATE(_string, GENERATESERIES(1, PATHLENGTH([pathx])))
var _GetVal = SELECTCOLUMNS(_generate, "Msg", PATHITEM([pathx], [Value]))
return
_GetVal

If you have always message.count:::ge::: like string at the end, you can follow these steps in Power Query-
Step 1: Duplicate you message column
Step-2: apply split on new duplicated column using string message.count:::ge::: and you will have a new column with last Numeric value from your original text.
Step-3: you can now apply filter on the new column.
Sample Output-

Related

Using value from allselected in a measure to filter rows in another measure

I want to use the selected slicer value in string format to filter rows in a table in a visual.
So, I created the following measure:
SlicerVal = ALLSELECTED(Table[Column1])
The follow up measure is as follows:
TotalRows = CALCULATE(COUNTROWS(Table),filter(Table, Table[Column2] = [SlicerVal]))
However.. This returns completely different data. When hardcoding the string value the correct data is returned, like in the example below:
TotalRows = CALCULATE(COUNTROWS(Table),filter(Table, Table[Column2] = "A"))
Is there a way to convert the measure value to a string somehow, which can be used dynamically to correspond the string value filter to the selected slicer value?
How about this?
TotalRows = CALCULATE(COUNTROWS(Table),filter(Table, Table[Column2] IN ALLSELECTED(Table[Column1])))
[Question: are you intentionally filtering on all selected elements from Column1 when applying a conditions onto Column2? I have no idea about your use-case, that's why -- for safety reasons -- I'm asking...]

PowerBI: Aggregate Measure correctly by condition on DATEDIFF

I have the following Table:
BaseTable
It represents processes with a certain category.
And there is also a Date Table over column TIMESTAMP.
I would like to show a Measure based on another Measure that calculates the Date-Difference until the selected Date.
So first this is how I calculate the Date-Difference:
AGE =
VAR SELECTED_DATE = CALCULATE(MAX(DATUM[Date]), ALLSELECTED(DATUM))
VAR STARTDATE_PROCESS = Calculate(MAX(Workflow[MIN_TIMESTAMP]),DATUM[Date]<=MAX(DATUM[Date]), ALL(DATUM[Date]))
RETURN
DATEDIFF(STARTDATE_PROCESS,SELECTED_DATE,DAY)
Now I want to use a Measure which depends on the result of AGE, like
NEW = IF([AGE]<=3,CALCULATE(COUNT(Workflow[PROCESS]),DATUM[Date]<=MAX(DATUM[Date]),ALL(DATUM)))
or
OLD = IF([AGE]>3,CALCULATE(COUNT(Workflow[PROCESS]),DATUM[Date]<=MAX(DATUM[Date]),ALL(DATUM)))
The Measures AGE, OLD and NEW look like that with the Base Table:
Measures
As you can see the aggregation is not working correctly:
Result_Wrong
But it should be like that
Result_Correct
Any idea how to fix that?
Thank you!
So the problem is that the subtotal is calculated at a whole different context, and because your Age measure is based on the MAX(Workflow[MIN_TIMESTAMP]) that won't take into account that there can be multiple processes.
To do what you want, you need to change the New and Old measures to perform an aggregation per process and then return the result of that. Something like this:
New_agg =
VAR tbl = ADDCOLUMNS(CALCULATETABLE(VALUES(Workflow[Process]), ALL('Date')), "age", [Age], "count_process", CALCULATE(COUNT(Workflow[Process]), ALL('Date')))
RETURN SUMX(tbl, IF([age]<=3, [count_process]))
Demo File
Let me know if below solution is working
Unfortunately I am unable to generate the dummy data that you have been using, so Created my own data for developing the solution.
Now from this data I have calculated the difference of dates and put it as Age
Now to get the count of process for the condition like yours, I have created two formulas and the result is:
Logic I followed here is, instead of creating measure I have created columns and took the sum of those columns which will give the data you need as sum of those columns.
Column for New:
New = IF((Sheet1[Age]) > 20, 1,0)
Column for Old:
Old = IF((Sheet1[Age]) < 20, 1,0)
Now place both formulas in "Values" and take sum as the aggregation.
Final result is

How to create a complex filter from a single value passed in from USERNAME() function

I am generating Power BI embedded tokens for Row Level Security.
The token contains a value of a role for the USERNAME() function to receive, which is then used in the Table filter DAX expression, e.g.: [Region] = USERNAME(). This works when a value (say West) is passed in from the token, and the sales report will be filtered by the West Region.
Next, I need to add additional filters like: [Region] = USERNAME() && [Customer] IN {"Delta", "Echo"}. I've tried to pass in West|Delta|Echo to USERNAME() and changed the DAX expression to:
[Region] = LEFT(USERNAME(), FIND("|", USERNAME())-1) && [Customer] IN {"Delta", "Echo"}
This version worked, but the list for IN filter had to be hard-coded.
Is there a way to write a DAX expression to extract multiple values delimited by | and create a list for the IN operator shown above?
I'd have a table in the middle, and then link the appropriate fields to that table, so West|Delta|Echo would be 2 rows: West, Delta and West,Echo. Then this table has relationships (one directional) to the Region and Customer tables.
In line with what you are currently doing, and if there are no overlaps between the Customer entries (e.g., no Echo and Echo2), you can use CONTAINSSTRING(USERNAME(), [Customer])

IF condition in DAX is creating Cartesian Join on rows

Dax formula without If condition works fine, but as soon as I add an IF condition rows start multiplying. I believe it's doing Cartesian Product.
My requirement is simple. I need to show only those rows in which Sickness[Start_Date]>LASTDATE(Test[Date])
The complete formula is -
Measure =
var val = CALCULATE(MAX(Sickness[Start_Date]),FILTER(Sickness,Sickness[Start_Date]>LASTDATE(Test[Date])),ALL())
return
IF(val = BLANK(),0,1)
I have 3 separate tables Emp_data, Test and Sickness.
To replicate this scenario, Please follow the below steps:
1st Step : Create table Emp_data
Emp_data = DATATABLE("Emp_no",INTEGER,"Name",STRING,{{101,"A"},
{102,"B"},
{103,"C"},
{104,"D"},
{105,"E"},
{106,"F"},
{107,"G"},
{108,"I"},
{109,"J"},
{110,"K"},
{111,"L"},
{112,"N"},
{113,"M"},
{114,"O"},
{115,"P"},
{116,"Q"},
{117,"R"},
{118,"S"},
{119,"T"},
{120,"U"}
})
create table : Test
Test = DATATABLE("Emp_No",INTEGER,"Date",DATETIME,"Result",INTEGER,{{101,"3/10/2020",1},
{101,"3/13/2020",2},
{102,"3/11/2020",1},
{103,"3/12/2020",2},
{104,"3/13/2020",1},
{105,"3/14/2020",1},
{106,"3/15/2020",2},
{107,"3/16/2020",1},
{108,"4/20/2020",1},
{109,"4/21/2020",2},
{110,"4/22/2020",2},
{111,"4/23/2020",1},
{112,"4/24/2020",1},
{113,"4/25/2020",2},
{114,"4/26/2020",1},
{115,"4/27/2020",2},
{116,"5/5/2020",1},
{117,"5/5/2020",1},
{118,"5/5/2020",1},
{119,"5/5/2020",1},
{120,"5/5/2020",2}
})
Create table Sickness
Sickness = DATATABLE("Emp_no",INTEGER,"Start_Date",DATETIME,"End_Date",DATETIME,"Sickness_Code",INTEGER,{{101,"2/12/2020","2/12/2020",30},
{101,"3/10/2020","3/15/2020",50},
{101,"3/20/2020","3/30/2020",50},
{101,"4/5/2020","4/10/2020",40},
{102,"3/11/2020","3/11/2020",50},
{107,"3/1/2020","3/2/2020",30},
{107,"3/15/2020","3/20/2020",50},
{107,"3/21/2020","3/31/2020",40},
{112,"4/20/2020","4/30/2020",50},
{112,"5/1/2020","5/15/2020",50},
{116,"4/1/2020","4/15/2020",30},
{116,"5/3/2020","5/15/2020",50},
{116,"5/16/2020","5/26/2020",50},
{116,"5/27/2020","5/29/2020",40}}
)
Second Step is to create relationship between these 3 tables. Emp_Data and Test table have one to many relationship. I changed the filter direction to BOTH. Thinking may be this will resolve the issue. Create relation many to many between the tables Test and Sickness. The image is attached
The output is as follows :
If I remove the IF condition my out is what I need :
Can someone help me in understanding this behavior of Power BI. This looks very strange. Why row count is increasing after applying IF condition. Thanks in advance
It's because you assigned a 0 value to all blank values in your Sickness data table. Once your remove the if statement, Power BI only shows data rows that do not return a blank value.
To fix your issue try this updated meassure:
Measure =
VAR val = CALCULATE(MAX(Sickness[Start_Date]),FILTER(Sickness,Sickness[Start_Date]>LASTDATE(Test[Date])),ALL())
VAR OneZero = IF(ISBLANK(val),0,1)
RETURN
IF(HASONEVALUE(Sickness[Emp_no],OneZero)

Frequency Counter

Good evening everyone, I'm having trouble resolving the following question:
I have "Table 1" containing the occurrence records and "Table 2" containing the occurrences.
I need to set up a VIRTUAL TABLE or VIEW TABLE that presents the occurrences and their frequencies as follows:
Tables with Perspective
The most I could do was bring the occurrences with the total number of rows in the table, ie the same amount X for all.
Last try using DaxStudio
You need to create a measure to show the numbers in the report.
But first, it is recommended to transform the table into a form like below, where each occurrence appears in each row. This has a lot of advantage to make the DAX measure simpler, more accurate, and run faster.
This can be easily achieved using Power Query Editor. The required steps are,
Select the comma delimited occurrences column.
In Transform tab, click Split Column and choose By Delimiter.
Make sure Comma and split at Each occurrence of the delimiter is selected by default.
In Advanced options, select split into Rows, then click OK.
Then you can define a measure to count the number of occurrences, which is as simple as below.
Count = COUNTROWS ( Tabela1 )
Now, in the report area, you can use the measure to obtain the desired output.
I have recreated your tables and here is the DAX for Table3 (perspectiva):
Table3 =
VAR uniqueOccurences = DISTINCT(Table2[Occurence])
RETURN
ADDCOLUMNS(uniqueOccurences,
"count",
VAR currentOccurence = [Occurence]
RETURN
CALCULATE(COUNTA(Tabel1[ID]),
FILTER(Tabel1, CONTAINSSTRING(Tabel1[Occurences], currentOccurence) = TRUE()))
)
This returns the following table:
Please mark this as the solution if this answered your question :)