PowerBI how to calculate response time with DAX? - powerbi

For example:
1.7.2021 10.49.03 TAK001 received a message from VEH270 with MessageId "AS8PR01M"
3.7.2021 11.58.03 TAK001 replied for this message as AS8PR01M is found from References column and TAK001 is sender and DisplayTo is including VEH270.
I would need to calculate datedifference between these to dates. Could someone help to solve this, thanks?
Sender DisplayTo DateTimeSent DateTimeReceived MessageId References
TAK001 TAM210 28.10.2021 11.31.48 28.10.2021 11.31.50 AM7PR01M HE1PR0101
TAM210 TAK001 18.10.2021 11.24.18 18.10.2021 11.24.19 HE1PR0101
TAK001 VEH270, TAA770 3.7.2021 11.58.03 3.7.2021 11.58.05 DU2PR01M AS8PR01M
VEH270 TAK001 1.7.2021 10.48.59 1.7.2021 10.49.03 AS8PR01M

I think I got this at least someway sorted out:
Response time =
VAR Responseday = CALCULATE(
MIN(Sheet1[DateTimeReceived]),
FILTER(Sheet1,[References] = EARLIER([MessageId]))
)
VAR Receiveday = [DateTimeReceived]
RETURN
DATEDIFF(Receiveday,Responseday,DAY)

If I understand correctly, based on your example table: when there is a value in the References column, it means that this row is the reply to the referenced MessageID.
The most difficult thing based on your example is the handling or the time strings. 28.10.2021 11.31.48 cannot be handled as date/time out of the box.
So, here is the DAX for a calculated column to calculate the response time, in minutes:
ResponseTime =
VAR Date1_String =
MINX(
CALCULATETABLE(
Table,
[Reference] = EARLIER([MessageId])
),
[DateTimeReceived]
)
VAR Date2_String = [DateTimeSent]
VAR Date1_Date =
FORMAT(
DATEVALUE(
SUBSTITUTE(
LEFT(
Date1_String,
FIND(" ", Date1_String)
),
".",
"/"
)
),
"dd/mm/yyyy"
) +
TIMEVALUE(
SUBSTITUTE(
RIGHT(
Date1_String,
FIND(" ", Date1_String)
),
".",
":"
)
)
VAR Date2_Date =
FORMAT(
DATEVALUE(
SUBSTITUTE(
LEFT(
Date2_String,
FIND(" ", Date2_String)
),
".",
"/"
)
),
"dd/mm/yyyy"
) +
TIMEVALUE(
SUBSTITUTE(
RIGHT(
Date2_String,
FIND(" ", Date2_String)
),
".",
":"
)
)
RETURN
IF(
NOT ISBLANK([References]),
DATEDIFF(
Date1_Date,
Date2_Date,
MINUTE
),
BLANK()
)
The code introduces a few variables :
Date1_String retrieves the DateTimeReceived from the initial message searching for the message with the MessageId in the current Reference column.
Date2_String is the DateTimeSent from the current line. i.e. the reply.
Date1_Date and Date2_Date is a (slightly convoluted) way to parse the string into a workable date/time format.
After the RETURN, a simple IF statement than calculate the time difference in minutes between the two date if only the column References is not empty.

Related

Count Specific Word by Row in DAX

I'm trying to count the number of times the word "text" appears per row in Power BI. I've done a lot of google searching and seen examples like this:
Formula :=
CALCULATE (
COUNTROWS ( FILTER ( 'TestData', FIND ( "text", 'TestData'[Description],, 0 ) > 0 ) ),1=1
)
but it isn't quite getting me there. How can I get for row 1, a result of 1 and row 2, a result of 3.
CREATE TABLE [dbo].[TestData](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Description] [varchar](100) NULL
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[TestData] ON
GO
INSERT [dbo].[TestData] ([ID], [Description]) VALUES (1, N'this is my demo text')
GO
INSERT [dbo].[TestData] ([ID], [Description]) VALUES (2, N'text text demo text')
GO
SET IDENTITY_INSERT [dbo].[TestData] OFF
GO
Expected Result
ID Description Text Word Count
1 this is my demo text 1
2 text text demo text 3
Calculated Column:
=
VAR MySearchText = "text"
RETURN
DIVIDE(
LEN( Table1[Description] )
- LEN( SUBSTITUTE( Table1[Description], MySearchText, "" ) ),
LEN( MySearchText )
)
Measure:
=
VAR MySearchText = "text"
VAR ThisDescription =
MIN( Table1[Description] )
RETURN
DIVIDE(
LEN( ThisDescription )
- LEN( SUBSTITUTE( ThisDescription, MySearchText, "" ) ),
LEN( MySearchText )
)
though note that both of these will return positive counts where MySearchText is found within other words: a description of "this is textual", for example, will return 1.
I don't believe DAX has a textsplit function, but you can do something like this to ensure you don't pick up words of which text is a substring.
Text Count (DAX) =
VAR pad = SUBSTITUTE(" " & [Description] & " ","text","~text~")
VAR lenPad = LEN(pad)
VAR lenText = LEN("~text~")
VAR lenRemText = LEN(SUBSTITUTE(pad,"~text~",""))
RETURN (lenPad-lenRemText)/lenText
```

arguments in generate series cannot be blank error

i am trying to apply levenshtein distance to 2 columns, tables and getting error in generate series cannot be blank.Here is my code.
Measure =
VAR SlicerText =
SELECTEDVALUE ( 'Slicer Table'[TestColumn] )
VAR TableText =
SELECTEDVALUE ( 'Table'[TestColumn] )
VAR length =
MAX ( LEN ( SlicerText ), LEN ( TableText ) )
VAR TestTable =
ADDCOLUMNS (
GENERATESERIES ( 1, length, 1 ),
"InSlicer", MID ( SlicerText, [Value], 1 ),
"InTable", MID ( TableText, [Value], 1 )
)
RETURN
COUNTROWS ( FILTER ( TestTable, [InSlicer] = [InTable] ) )
/ COUNTROWS ( TestTable )
With a little effort you could have figured this out yourself:
The error message tells you that one of the parameters of GENERATESERIES() is blank. This can ONLY be the length variable.
length is blank when both variables SlicerText and TableText are blank.
both variables refer to the SELECTEDVALUE() function, which returns blank if none or more than one rows are selected and you didn't provide an alternateResult, see the official documentation here: SELECTEDVALUE
Bottom line: Make shure you have exactly one row selectd in 'Slicer Table' and 'Table'.
This is as much help as you can get, since you didn't share a minimal, reproducible example as recommended by StackOverflow.

DAX - Filter Table by Multi Select Filter Condition

Am trying to filter a table with Multi Selection Filter.
DAX: To select the values in the filter selected (Multi)
SelectedEnvironments =
CONCATENATEX (
VALUES ( Environments[ShortEnvName] ),
Environments[ShortEnvName],
", "
)
Result:
But when trying to filter table based on above filter variable doesnt return anything.
DAX:
Aggregated Usage =
VAR __SelectedEnvironments =
CONCATENATEX (
VALUES ( Environments[ShortEnvName] ),
Environments[ShortEnvName],
", "
)
RETURN
CALCULATETABLE (
LastestDBUsage,
LastestDBUsage[Environment] IN { __SelectedEnvironments }
)
If I hard code the values within IN operator it work fine. What am doing wrong? Do I need to format the string for IN operator
DAX (Works fine with Hard Code Values)
Aggregated Usage =
VAR __SelectedEnvironments =
CONCATENATEX (
VALUES ( Environments[ShortEnvName] ),
Environments[ShortEnvName],
", "
)
RETURN
CALCULATETABLE (
LastestDBUsage,
LastestDBUsage[Environment] IN { "DEV", "TST" }
)
Actually, the IN operator works on tables, CONCATENATEX returns a string.
{ __SelectedEnvironments }
returns a table with one row consisting of one column like for instance "DEV, TST"
to make the code work it would be changed to use a table instead, like for instance
Aggregated Usage =
VAR __SelectedEnvironments = VALUES ( Environments[ShortEnvName] )
RETURN
CALCULATETABLE (
LastestDBUsage,
LastestDBUsage[Environment] IN __SelectedEnvironments
)

Convert comma separated text to a list of numbers

In Power BI, I have created a DAX query created with a var giving comma-separated text using CONCATENATEX function.
Output like
Var = "1,2,3,4,5,6"
Now I want to search this var into my table column with syntax
Table[col] in {var}.
It is throwing an error.
I even tried converting the column to string with syntax
Convert(table[col], string) in {var}
The error is removed but the data doesn't match with column data.
I found this Power BI community thread that is essentially the same question.
The solution is to convert the string into a path object.
Here's the code from the link:
Measure 3 =
VAR mymeasure =
SUBSTITUTE ( [Measure], ",", "|" )
VAR Mylen =
PATHLENGTH ( mymeasure )
VAR mytable =
ADDCOLUMNS (
GENERATESERIES ( 1, mylen ),
"mylist", VALUE ( PATHITEM ( mymeasure, [Value] ) )
)
VAR mylist =
SELECTCOLUMNS ( mytable, "list", [mylist] )
RETURN
CALCULATE ( COUNTROWS ( Table1 ), Table1[ID] IN mylist )
There's a bit of redundancy in the above, so I'd probably condense it a bit and write it like this:
SomeMeasureFilteredByVar =
VAR PathVar = SUBSTITUTE ( [Var], ",", "|" )
VAR VarList =
SELECTCOLUMNS (
GENERATESERIES ( 1, PATHLENGTH ( PathVar ) ),
"Item", VALUE ( PATHITEM ( PathVar, [Value] ) )
)
RETURN
CALCULATE ( [SomeMeasure], 'Table'[ID] IN VarList )
Edit: To just create a calculated table, you can skip the last step:
TableFromString =
VAR PathVar = SUBSTITUTE ( "1,2,3,4,5,6", ",", "|" )
RETURN
SELECTCOLUMNS (
GENERATESERIES ( 1, PATHLENGTH ( PathVar ) ),
"Item", VALUE ( PATHITEM ( PathVar, [Value] ) )
)
Note that it is not possible to create a calculated table that is dynamically responsive to report filters and slicers. Materialized calculated tables are only calculated once when the data loads, not every time you adjust a filter or slicer.
Therefore, you can use a measure in the table instead of the string "1,2,3,4,5,6" but the table output will be the same regardless of what the measure returns within different filter contexts.

Find the last value after the dot in DAX e.g. in value1.value2.value3 finds value3

I have a column with a dotted value e.g
project.phase.task
project.task
project.phase.subphase.task
in each instance I want the last doted value.
I am using the DAX function:
lastVal =
var i = FIND(".",'My Table'[wbs],1,-1)
return
if(i>0,mid('My Table'[wbs],i+1,99),"")
There is no FindLast function. How would I simulate it?
This would be a similar problen to finding a file extension in a file name or path.
You don't need to do this with DAX. You can use Split Column function of the Query Editor to get the part of the text after the right-most dot.
You can do this with DAX.
As a calculated column:
lastVal =
PATHITEMREVERSE (
SUBSTITUTE (
'My Table'[wbs],
".",
"|"
),
1
)
As a measure:
lastValMeasure =
VAR MyString =
IF (
HASONEVALUE ( 'My Table'[wbs] ),
FIRSTNONBLANK ( 'My Table'[wbs], 1 ),
BLANK()
)
RETURN
PATHITEMREVERSE (
SUBSTITUTE (
MyString,
".",
"|"
),
1
)
You can turn the string into an indexed list of characters and then take the characters after the maximally indexed ..
This should work as a calculated column:
lastVal =
VAR String = 'My Table'[wbs]
VAR StringLength = LEN ( String )
VAR StringToTable =
ADDCOLUMNS (
GENERATESERIES ( 1, StringLength ),
"Char", MID ( String, [Value], 1 )
)
VAR LastDot = MAXX ( FILTER ( StringToTable, [Char] = "." ), [Value] )
RETURN
RIGHT ( String, StringLength - LastDot )
If you need it as a measure, then simply adjust the String variable to take the appropriate aggregate. For example, MAX('My Table'[wbs]) or FIRSTNONBLANK('My Table'[wbs], 'My Table'[wbs]).