DAX Measure - Extrapolate last Date for COUNT - powerbi

I have a table that contains 3 columns:
Order
Date
State
Each row / record shows if the state was changed:
Now I would like to calculate the number of order that are below state 3 for each date in the calendar.
In the example above you can see there is nor entry for order 100 for 07.01.2022. But for this date the order is still below 3 as you can see in the record before.
How would you do that?

I think this might be better to do in PowerQuery.
Suppose the table mentioned in your question is order_state:
let
Source = Table.FromRows(
{
{100, 1, "1/1/2022"},
{100, 2, "1/5/2022"},
{100, 3, "1/8/2022"},
{101, 1, "1/5/2022"},
{101, 2, "1/6/2022"},
{101, 3, "1/7/2022"},
{102, 1, "1/7/2022"},
{102, 2, "1/9/2022"},
{102, 3, "1/10/2022"}
},
{"Order", "Status", "Date"}
),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Date", type date}})
in
#"Changed Type"
Then I believe you can calculate what you want with a query like this:
let
start_date = List.Min(order_state[Date]),
end_date = List.Max(order_state[Date]),
days = Duration.Days(end_date - start_date),
dates = Table.FromList(List.Dates(start_date,days,#duration(1, 0, 0, 0)), Splitter.SplitByNothing(), {"Date"}, null, ExtraValues.Error),
joined = Table.AddColumn(
dates,
"order_state_rows",
(current) => Table.RowCount(
Table.Distinct(
Table.SelectColumns(
Table.SelectRows(
order_state,
(row) => (row[Date] <= current[Date] and row[Status] <> 3)
)
,{"Order"}
)
)
)
)
in
joined
Which gives this result:

Related

Powerquery: how to iterate/loop parameters list?

How to substitute code below with compact loop?
let
ParametersList = {"CustomerID","FirstName","LastName"},
Source1 = fnCheckId(srcTbl , ParametersList{0}),
Source2 = fnCheckId(Source1, ParametersList{1}),
Source3 = fnCheckId(Source2, ParametersList{2}),
Result = Source3
in
Result
Looping Problems:
It should loop ParametersList
current loop output table should work as input Table for next loop
SIMPLIFIED EXAMPLE DETAILS (Source File):
fnCheckId function example (in real business case much more complex):
(tbl as table, clm as text)=>
let
//tbl = srcTbl, clm = "FirstName",
#"Added Custom" = Table.AddColumn(tbl,"QA "&clm, each if Text.Length(Record.Field(_, clm))>3 then "Ok" else "Nok")
in
#"Added Custom"
Source Table:
Table.FromRows(
{
{1, "Bob", "Smith", "123-4567"},
{2, "Jim", "Brown", "987-6543"},
{3, "Paul", "Wick", "543-7890"}
},
{"CustomerID", "FirstName", "LastName", "Phone"}
)
Estimated Result Table:
With original function, how about
let srcTbl = Table.FromRows(
{
{1, "Bob", "Smith", "123-4567"},
{2, "Jim", "Brown", "987-6543"},
{3, "Paul", "Wick", "543-7890"}
},
{"CustomerID", "FirstName", "LastName", "Phone"}
),
List = {"CustomerID", "FirstName", "LastName"},
#"Unpivoted Only Selected Columns" = Table.Unpivot(srcTbl, List, "Attribute", "Value"),
Source1 = fnCheckId(#"Unpivoted Only Selected Columns","Value"),
#"Removed Columns" = Table.RemoveColumns(Source1,{"Value"}),
#"Renamed Columns" = Table.RenameColumns(#"Removed Columns",{{"QA Value", "Value"}}),
#"Change Title" = Table.TransformColumns(#"Renamed Columns",{{"Attribute",each "QA" & _, type text}}),
combined = #"Unpivoted Only Selected Columns" & #"Change Title",
#"Changed Type" = Table.TransformColumnTypes(combined,{{"Attribute", type text}, {"Value", type text}}) ,
#"Pivoted Column" = Table.Pivot(#"Changed Type", List.Distinct(#"Changed Type"[Attribute]), "Attribute", "Value")
in #"Pivoted Column"
or with changed function as below,
let srcTbl = Table.FromRows(
{
{1, "Bob", "Smith", "123-4567"},
{2, "Jim", "Brown", "987-6543"},
{3, "Paul", "Wick", "543-7890"}
},
{"CustomerID", "FirstName", "LastName", "Phone"}
),
List = {"CustomerID", "FirstName", "LastName"},
#"Unpivoted Only Selected Columns" = Table.Unpivot(srcTbl, List, "Attribute", "Value"),
#"Changed Type1" = Table.TransformColumnTypes(#"Unpivoted Only Selected Columns",{{"Value", type text}}),
#"Processed" = Table.TransformColumns(#"Changed Type1",{{"Value",each fnCheckId2(_), type text}}),
Namechange = Table.TransformColumns(Processed,{{"Attribute",each "QA "&_, type text}}),
combined = #"Changed Type1" & Namechange,
#"Pivoted Column" = Table.Pivot(combined, List.Distinct(combined[Attribute]), "Attribute", "Value")
in #"Pivoted Column"
with fnCheckId2
( clm as text)=>
let
z = if Text.Length(clm )>3 then "Ok" else "Nok"
in z
Please try this loop example:
loops ParametersList list
Use fnCheckId function output table as input for next loop
Do NOT require knowledge about looping function fnCheckId
Recursive function Loop_fnCheckId:
(Loop as number, inTbl as table, inPrm as list )=>
try Loop_fnCheckId(Loop-1, fnCheckId(inTbl, inPrm{Loop-1}),inPrm)
otherwise inTbl
code with loop:
let
ParametersList = {"CustomerID","FirstName","LastName"},
cntLoop = List.Count(ParametersList),
Result = Loop_fnCheckId(cntLoop,srcTbl, ParametersList)
in Result
P.S. The question: is it possible to rewrite it using each _ syntax and avoid additional looping function Loop_fnCheckId

Group Items in Comma Separated values in Dax

I have following DAX code. I need comma separated holiday list based on Week No . I tired with CONCATENATEX function and it combine all comma separated holiday list in each row instead of week wise. Any one have any idea how we can achieve below expected using DAX.
Dax Code:
DEFINE
VAR A = UNION( ROW ("WeekNo", 1, "USAHoliday", "New Year", "CANHoliday","New Year")
,ROW ("WeekNo", 16, "USAHoliday", "Easter Sunday", "CANHoliday","Easter Sunday")
,ROW ("WeekNo", 16, "USAHoliday", "", "CANHoliday","Easter Monday")
,ROW ("WeekNo", 27, "USAHoliday", "Independence Day", "CANHoliday","")
,ROW ("WeekNo", 28, "USAHoliday", "", "CANHoliday","Independence Day")
,ROW ("WeekNo", 22, "USAHoliday", "Memorial Day", "CANHoliday","")
)
VAR AHoliday = DISTINCT(FILTER( UNION(SELECTCOLUMNS(A,
"WeekNo",[WeekNo]
,"Holiday",[USAHoliday]
),
SELECTCOLUMNS(A,
"WeekNo",[WeekNo]
,"Holiday",[CANHoliday]
)
),[Holiday]<>""))
VAR HolidayList=SUMMARIZE(AHoliday
,[WeekNo]
,"HolidayList.", CONCATENATEX(AHoliday,[Holiday],",", [Holiday],ASC)
)
EVALUATE HolidayList
Expected Result
HolidayList should be defined as, for example:
SUMMARIZE(
AHoliday,
[WeekNo],
"HolidayList",
CONCATENATEX(
FILTER( AHoliday, [WeekNo] = EARLIER( [WeekNo] ) ),
[Holiday],
", "
)
)

Grouped running total with Power Query M

This is how my table looks like (1.7 million rows):
I'm trying to build a running total per customer ID and date.
This is easy to express using DAX, but unfortunately I don't have enough memory on my machine (16GB RAM).
So, I'm trying to find an alternative with Power Query M using buffered tables, etc. but that is too complicated for me.
Can anyone help? Thank you so much in advance!
EDIT: After sorting by Date and CustomerID, added index and added a custom column with:
= Table.AddColumn(#"Added Index", "Personalizado", each (i)=>List.Sum(Table.SelectRows(#"Added Index", each [CustomerID]=i[CustomerID] and [Index]<=i[Index]) [Sales]))
I get the following:
EDIT2:
The whole code:
let
Origem = dataset,
#"Linhas Agrupadas" = Table.Group(Origem, {"Date", "CustomerID"}, {{"Sales", each List.Sum([Sales]), type nullable number}}),
#"Linhas Ordenadas" = Table.Sort(#"Linhas Agrupadas",{{"Date", Order.Ascending}, {"CustomerID", Order.Ascending}}),
#"Linhas Filtradas" = Table.SelectRows(#"Linhas Ordenadas", each [Sales] <> 0),
#"Added Index" = Table.AddIndexColumn(#"Linhas Filtradas", "Index", 0, 1, Int64.Type),
#"Personalizado Adicionado" = Table.AddColumn(#"Added Index","CumSum",(i)=>List.Sum(Table.SelectRows(#"Added Index", each [CustomerID]=i[CustomerID] and [Index]<=i[Index]) [Sales]), type number )
in
#"Personalizado Adicionado"
Method1
Sort your data to start with, perhaps on the date column and CustomerID column. However it appears on screen is the row order it is going to accumulate the total
Add column .. index column...
Add column .. custom column with formula
= (i)=>List.Sum(Table.SelectRows(#"Added Index", each [CustomerID]=i[CustomerID] and [Index]<=i[Index]) [Sales])
Right click index column and remove it
Likely adding a Table.Buffer() around the index step will help speed things up
Sample full code:
let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Sorted Rows" = Table.Sort(Source,{{"CustomerID", Order.Ascending}, {"Date", Order.Ascending}}),
#"Added Index" = Table.Buffer(Table.AddIndexColumn(#"Sorted Rows", "Index", 0, 1)),
#"Added Custom" = Table.AddColumn(#"Added Index","CumSum",(i)=>List.Sum(Table.SelectRows(#"Added Index", each [CustomerID]=i[CustomerID] and [Index]<=i[Index]) [Sales]), type number ),
#"Removed Columns" = Table.RemoveColumns(#"Added Custom",{"Index"})
in #"Removed Columns"
Method 2:
Create function fn_cum_total
(Input) =>
let withindex = Table.AddIndexColumn(Input, "Index", 1, 1),
cum = Table.AddColumn(withindex, "Total",each List.Sum(List.Range(withindex[Sales],0,[Index])))[Total]
in cum
Create query that uses that function to add cumulative totals to Sales column after grouping on CustomerID
let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Sorted Rows" = Table.Buffer(Table.Sort(Source,{{"CustomerID", Order.Ascending}, {"Date", Order.Ascending}})),
Running_Total = Table.Group(#"Sorted Rows",{"CustomerID"},{{"Data",
(Input as table) as table => let zz = fn_cum_total(Input),
result = Table.FromColumns(Table.ToColumns(Input)&{zz}, Value.Type(Table.AddColumn(Input, "total", each null, type number))) in result, type table}} ),
#"Expanded Data" = Table.ExpandTableColumn(Running_Total, "Data", {"Date", "Sales", "total"}, {"Date", "Sales", "total"})
in #"Expanded Data"
I cannot take credit for method 2, borrowed long ago, but do not recall source

Dynamicaly change chart from category to subcategory

I have a hierarchical matrix with a corresponding chart from this table:
let
t0 = Table.FromRows(
{
{"2020-01-01", "1", "10", 10},
{"2020-01-02", "1", "10", 3},
{"2020-01-01", "1", "11", 8},
{"2020-01-02", "1", "11", 15},
{"2020-01-01", "2", "20", 5},
{"2020-01-02", "2", "20", 9},
{"2020-01-01", "2", "21", 13},
{"2020-01-02", "2", "21", 12}
},
{"day", "cat", "subcat", "amount"}
),
t1 = Table.TransformColumnTypes(t0, {{"amount", Int64.Type}})
in
t1
I can make the page start the chart showing the line for each category, which is what I want, by choosing the category as the legend
Now I want that when I click on the category line in the matrix the chart dynamicaly shows the lines for the subcategories of that category. Is it possible or is there another approach leading to the same result?
I'm not sure if it's possible to do drill down within the visual like that but you can make it work if you have filtering from a slicer or another visual.
First, create a new independent table to use on the x-axis that has both cat and subcat:
CatSubcat = UNION ( VALUES ( t1[cat] ), VALUES ( t1[subcat] ) )
Then we need a corresponding measure to go with it that switches between cat and subcat:
Measure =
IF (
HASONEVALUE ( t1[cat] ),
CALCULATE ( SUM ( t1[amount] ), t1[subcat] IN VALUES ( CatSubcat[cat] ) ),
CALCULATE ( SUM ( t1[amount] ), t1[cat] IN VALUES ( CatSubcat[cat] ) )
)
If nothing is filtered, it should look like this:
If you filter using the matrix to the left (or via a slicer on t1[cat]), you get this:
For more than two levels, this related post may be of use.

Google visualization data table-getFilteredRows method

Im trying to filter column 'time' in visualization data table using getFilteredRows(filters) method.I provided column value with minimum and maximum values as,
var timesheet_dataTable = new google.visualization.DataTable(data, 0.6);
var time_filter = timesheet_dataTable.getFilteredRows([{column: 3, minValue: '2:28 PM', maxValue: '3:01 PM'}]);
and then created data view with setRows method to display the data but the table displayed without filtering the data.I checked with other column values and received proper output.So whether 'timeofday' data type is supported in this type of filters?
Is there any other method to filter column based on time?
Update:
This is the code for formatting and passing value to the visualization table.Value of variable startTime will be like '14:28:12'.
val datetimeStart: String = "Date(0,0,0,"
val datetimeEnd: String = ")"
val simpleDateTimeFormat = new SimpleDateFormat("HH,mm,ss")
Json.obj("v" -> JsString(datetimeStart + (simpleDateTimeFormat.format(tsl.startTime)).toString() + datetimeEnd))
before displaying in visualization table i have used formatter as:
var formatter_short1 = new google.visualization.DateFormat({pattern:'h:mm aa'});
formatter_short1.format(timesheet_dataTable,3);
The "timeofday" data type is supported by the filter method, you just need to use it correctly:
// filter column 3 from 2:28PM to 3:01PM
var time_filter = timesheet_dataTable.getFilteredRows([{
column: 3,
minValue: [14, 28, 0, 0],
maxValue: [15, 1, 0, 0]
}]);
var view = new google.visualization.DataView(timesheet_dataTable);
view.setRows(time_filter);
Make sure you are using the view you create to draw your chart, instead of the DataTable:
chart.draw(view, options);
[edit - example for filtering "datetime" type column]
// filter column 3 from 2:28PM to 3:01PM
var time_filter = timesheet_dataTable.getFilteredRows([{
column: 3,
minValue: new Date(0, 0, 0, 14, 28, 0, 0),
maxValue: new Date(0, 0, 0, 15, 1, 0, 0)
}]);
var view = new google.visualization.DataView(timesheet_dataTable);
view.setRows(time_filter);