Counting customers that have sales in the same products - dax

The data table has customers, products sales etc.
Based on a slicer selection products i want to count how many customers have sales in all selected products.
As below i only want to count customer B because he is the only one having all selected products
Customer a Product a product b product c
A. 1 1
B. 1 1 1
C. 1
D. 1 1
E. 1 1

OKay. I think Your table is this:
Then You need this dax code:
CustomerHavingAll3Products =
VAR Onlya =
CALCULATETABLE ( VALUES ( 'Product'[Customer] ), 'Product'[Product a] <> 0 )
VAR Onlyb =
CALCULATETABLE ( VALUES ( 'Product'[Customer] ), 'Product'[Product b] <> 0 )
VAR Onlyc =
CALCULATETABLE ( VALUES ( 'Product'[Customer] ), 'Product'[Product c] <> 0 )
VAR CombinedAll =
INTERSECT ( INTERSECT ( Onlya, Onlyb ), Onlyc )
RETURN
COUNTX ( CombinedAll, [Customer] )
If we test it on a table visual:
Please do not forget to click the down-pointing arrow on customer column on the filter pane, and ensure that "show items with no data" is checked, see the picture below

you can do it on power query side... totally dynamic...
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WclTSUTIEYjAVqxOt5AQVMISLOMOkgRSI74KuxRVJi1JsLAA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Customer = _t, #"Product a" = _t, #"product b" = _t, #"product c" = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Customer", type text}, {"Product a", Int64.Type}, {"product b", Int64.Type}, {"product c", Int64.Type}}),
count_columns = Table.ColumnCount(Source)-1,
#"Unpivoted Columns" = Table.UnpivotOtherColumns(#"Changed Type", {"Customer"}, "Attribute", "Value"),
#"Grouped Rows" = Table.Group(#"Unpivoted Columns", {"Customer"}, {{"Total Count", each Table.RowCount(_), Int64.Type}}),
#"Filtered Rows" = Table.SelectRows(#"Grouped Rows", each [Total Count] = count_columns )
in
#"Filtered Rows"

Related

Max Group Filter Power Query

I'm trying to use the following code to get a new added column with information about a max value from a given field.
But what I would want is to have the possiblity to group a table where I filter it by a condition where the Custom column value would be 1.
I need to transform somehow the following parte of the code:
[
filter = [ID] /*should I add here another filter?/,
max2=Table.Group(
Source, {"ID"},
{{"MaxFiltered2", each List.Max([CODE])}}
){[ID=filter]}[MaxFiltered2]
][max2]
)
Here follows the code sequence:
#"Added Custom" = Table.AddColumn(
#"Changed Type",
"maxInt",
each
[
filter = [ID],
max=Table.Group(
Source, {"ID"},
{{"MaxFiltered", each List.Max([TAX])}}
){[ID=filter]}[MaxFiltered]
][max]
),
#"Added Custom1" = Table.AddColumn(#"Added Custom", "Custom", each if [maxInt]=[TAX] then 1 else 0),
#"Filtered Rows" = Table.SelectRows(#"Added Custom1", each ([Custom] = 1)),
#"Added Custom2" = Table.AddColumn(
#"Changed Type",
"maxInt2",
each
[
filter = [ID],
max2=Table.Group(
Source, {"ID"},
{{"MaxFiltered2", each List.Max([CODE])}}
){[ID=filter]}[MaxFiltered2]
][max2]
)
in
#"Added Custom2"
Inputput desired:
ID TAX CODE
A 4 921
A 6 500
A 6 200
B 2 700
B 2 500
B 1,5 100
Output desired:
ID TAX CODE
A 6 500
B 2 700
(to get the max for A and B IDs both on TAX and CODE variables)
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WclTSUTIBYksjQ6VYHQjfDIhNDQxQ+EZQvhOIDcTmaHxTJL6hnimIBInEAgA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [ID = _t, TAX = _t, CODE = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"ID", type text}, {"TAX", type number}, {"CODE", Int64.Type}}),
#"Grouped Rows" = Table.Group(#"Changed Type", {"ID"}, {{"All", each _, type table [ID=nullable text, TAX=nullable number, CODE=nullable number]}}),
#"Added Custom" = Table.AddColumn(#"Grouped Rows", "Custom",
each Table.First(
Table.Sort([All],{{"TAX", Order.Descending},{"CODE", Order.Descending}})
)
),
#"Removed Columns" = Table.RemoveColumns(#"Added Custom",{"ID", "All"}),
#"Expanded Custom" = Table.ExpandRecordColumn(#"Removed Columns", "Custom", {"ID", "TAX", "CODE"}, {"ID", "TAX", "CODE"})
in
#"Expanded Custom"
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WclTSUTIBYksjQ6VYHQjfDIhNDQxQ+EZQvhOIDcTmaHxTJL6hnimIBInEAgA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [ID = _t, TAX = _t, CODE = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"ID", type text}, {"TAX", type number}, {"CODE", Int64.Type}}),
#"Grouped Rows" = Table.Group(#"Changed Type", {"ID"}, {{"TAX", each List.Max([TAX]), type nullable number}, {"CODE", each List.Max([CODE]), type nullable number}})
in
#"Grouped Rows"

Power Query - Can a range be queried using SQL?

I have a range named tDetails. How can I query this using SQL?
I click in my range, and on the Power Query tab, I click "From Table/Range". This opens the Power Query editor.
In the advanced editor, I see something like:
let
Source = Excel.CurrentWorkbook(){[Name="tDetails"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"User ID", type text},
{"Company", type text},
{"State", type text},
{"Billed", type Int65.Type}})
in
#"Changed Type"
How do I go about querying this data? I'm needing to do things like:
SELECT 'UserID' = "User ID"
, 'Discount' = "Billed" * .51
, 'Note' = CASE WHEN State = 'NY' THEN 'Standard'
WHEN State = 'OH' THEN 'Second'
WHEN State = 'CA' THEN 'Third'
ELSE 'Fourth' END
FROM Source
WHERE "State" = "NY"
Also, can temp tables be used here?
SELECT 'UserID' = "User ID"
, 'Discount' = "Billed" * .51
INTO #UserDiscount
FROM Source
WHERE "State" = "NY"
SELECT * FROM #UserDiscount ORDER BY Discount DESC
These are super basic examples. What I really need to do is far more complex, but this would give me a place to start.
Thanks!
I think the equivalent Power Query would be
let
Source = Excel.CurrentWorkbook(){[Name="tDetails"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"User ID", type text},
{"Company", type text},
{"State", type text},
{"Billed", type Int65.Type}})
#"Filtered Rows" = Table.SelectRows(#"Changed Type", each ([State] = "NY")),
#"Added Custom" = Table.AddColumn(#"Filtered Rows", "Discount", each [Billed]*0.51),
#"Added Custom1" = Table.AddColumn(#"Added Custom", "UserID", each [UserID]),
#"Removed Other Columns" = Table.SelectColumns(#"Added Custom1",{"UserID", "Discount", "Billed"})
in
#"Removed Other Columns"
Also, the equivalent of SQL #temp table in Power Query would be use of table variable. In power query each step is table variable, e.g. Source, #"Changed Type", #"Filtered Rows", #"Added Custom".... which contains the table that was evaluated in that step. You can keep on utilizing the tables contained in each table variable in succeeding steps.
e.g.
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMlTSUcrPS1WK1YlWMgKyS8rzwWxjEDujKBUoEwsA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Column1 = _t, Column2 = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Column1", Int64.Type}, {"Column2", type text}}),
Custom0 = Table.SelectRows(#"Changed Type", each ([Column2] = "one")),
Custom1 = Table.SelectRows(#"Changed Type", each ([Column2] = "two")),
Custom2 = Table.SelectRows(#"Changed Type", each ([Column2] = "three")),
Custom3 = Custom0&Custom1&Custom2
in
Custom3
Yes, but you have to use a reserved function SqlExpression.ToExpression, and it doesn't look like your SQL is "valid" according to Power Query which likely needs in T-SQL format, so you'll have to experiment with how quotes are handled and columns renamed.
See this page for details: https://bengribaudo.com/blog/2021/07/13/5868/m-mysteries-sqlexpression-toexpression
Queries:
// tDetails
// Input from Excel range. This example uses embedded data so you can replicate my result.
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WcspPUtJRcs7PK8kvzgey/CKBhKGRsYlSrE60kldqWhqKtL8HSNoADJRiYwE=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"User ID" = _t, Company = _t, State = _t, Billed = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"User ID", type text}, {"Company", type text}, {"State", type text}, {"Billed", Int64.Type}})
in
#"Changed Type"
// Result
// Executes translated M code
let
ReferenceTables = [Source = tDetails],
Source = Expression.Evaluate(SQL, #shared)(ReferenceTables)
in
Source
// SQL
// Translates SQL to M
let
ReferenceTables = [Source = tDetails],
SqlQuery = "SELECT [User ID] as UserID, Billed * 0.51 as Discount, 'Standard' as [Note] FROM Source WHERE State = 'NY'",
TranslatedToM = SqlExpression.ToExpression(SqlQuery, ReferenceTables)
in
TranslatedToM
tDetails:
My SQL that works: SELECT [User ID] as UserID, Billed * 0.51 as Discount, 'Standard' as [Note] FROM Source WHERE State = 'NY'
Result:

Group records - keeping first Start Date (oldest) and last End Date (most recent)

I'm new to Power Query, so I'm hoping someone can help me with this problem. 
I have a dataset with ID, Status, Start Date and End Date. There are multiple rows for each ID with different start and end dates. Here's a sample of my dataset.
ID
Status
Start Date
End Date
1
A
01/04/2015
28/05/2015
1
A
28/05/2015
15/06/2016
1
B
15/06/2016
19/06/2016
1
B
19/06/2016
31/07/2016
1
B
31/07/2016
2
B
01/03/2017
03/06/2018
2
A
03/06/2018
07/08/2018
2
A
07/08/2018
31/12/2018
2
C
31/12/2018
01/09/2019
2
C
01/09/2019
03/05/2020
2
A
03/05/2020
I want to group consecutive rows (End Date same as the Start Date of next row) with same status for each ID and take the oldest Start Date and the most recent End Date. End Date will be blank for records that are still active. Here is the the output I'm looking for. 
ID
Status
Start Date
End Date
1
A
01/04/2015
15/06/2016
1
B
15/06/2016
2
B
01/03/2017
03/06/2018
2
A
03/06/2018
31/12/2018
2
C
31/12/2018
03/05/2020
2
A
03/05/2020
Is this possible? 
Many Thanks for your help.
This M code seems to work for what you described. It starts with your sample data in a table named Table1 in an Excel spreadsheet.
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Added Index" = Table.AddIndexColumn(Source, "Index", 0, 1, Int64.Type),
#"Added Custom" = Table.AddColumn(#"Added Index", "New Start Date",
each if [Index] = 0 or ([Index] > 0 and [ID] = #"Added Index"[ID]{[Index]-1} and [Status] <> #"Added Index"[Status]{[Index]-1}) then [Start Date]
else if [ID] <> #"Added Index"[ID]{[Index]-1}
then [Start Date]
else null),
#"Added Custom1" = Table.AddColumn(#"Added Custom", "New Finish Date",
each if [Index] = List.Last(#"Added Index"[Index]) or ([ID] <> #"Added Index"[ID]{[Index]+1} or [Status] <> #"Added Index"[Status]{[Index]+1}) then [End Date]
else null),
#"Filled Down" = Table.FillDown(#"Added Custom1",{"New Start Date"}),
#"Added Custom2" = Table.AddColumn(#"Filled Down", "Date Flag",
each if [Index] = 0
then if ([ID] <> #"Filled Down"[ID]{[Index]+1} or [Status] <> #"Filled Down"[Status]{[Index]+1}) or ([ID] = #"Filled Down"[ID]{[Index]+1} and [Status] = #"Filled Down"[Status]{[Index]+1} and [New Start Date] <> #"Filled Down"[New Start Date]{[Index]+1})
then 1
else 0
else if [Index] = List.Last(#"Filled Down"[Index])
then 1
else if ([ID] = #"Filled Down"[ID]{[Index]-1} and [Status] = #"Filled Down"[Status]{[Index]-1} and [New Start Date] <> #"Filled Down"[New Start Date]{[Index]+1}) or ([ID] = #"Filled Down"[ID]{[Index]+1} and [Status] <> #"Filled Down"[Status]{[Index]+1} and [New Start Date] <> #"Filled Down"[New Start Date]{[Index]+1})
then 1
else 0),
#"Filtered Rows" = Table.SelectRows(#"Added Custom2", each ([Date Flag] = 1)),
#"Removed Other Columns" = Table.SelectColumns(#"Filtered Rows",{"ID", "Status", "New Start Date", "New Finish Date"})
in
#"Removed Other Columns"
First. You must change null value in End Data with Today Data
Second. Group by advanced... ID and Status with 2 New column name: min for Start data and max for End data
Below you have the code:
P.S. #Promoted Headers is necessary only in my sample.
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Column1", type any}, {"Column2", type text}, {"Column3", type any}, {"Column4", type any}}),
#"Promoted Headers" = Table.PromoteHeaders(#"Changed Type", [PromoteAllScalars=true]),
#"Changed Type1" = Table.TransformColumnTypes(#"Promoted Headers",{{"ID", Int64.Type}, {"Status", type text}, {"Start Date", type datetime}, {"End Date", type datetime}}),
#"Replaced null withToday" = Table.ReplaceValue(#"Changed Type1",null,DateTime.LocalNow(),Replacer.ReplaceValue,{"End Date"}),
#"Grouped Rows" = Table.Group(#"Replaced null withToday", {"ID", "Status"}, {{"Minim Data (1)", each List.Min([Start Date]), type nullable datetime}, {"Maxim Data (1)", each List.Max([End Date]), type nullable datetime}})
in
#"Grouped Rows"
Thanks #Marc Pincince and #Marius Durlea for your response. As #Storax' comments, I have got the solution now and it is here. Adding the code below too.
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("bZBLDoUgDEW3Yjom6YeHwFDfMoz734YtEKXRAYN7esItHAcwBNj0ECP9UIiTBilIqYczPM6EA3BCWi2st7N7rKF+O3VyohbntzPhAEsbyRjZqtFG2UIcd5Xb2TzWkJHKh/Pg1sfinb/HvbhaqM6ZcC+2PxJ67TNwe855AQ==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [ID = _t, Status = _t, #"Start Date" = _t, #"End Date" = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"ID", Int64.Type}, {"Status", type text}, {"Start Date", type date}, {"End Date", type date}}),
#"Grouped Rows" = Table.Group(#"Changed Type", {"ID", "Status"}, {{"Start Date", each List.First([Start Date]), type nullable date}, {"End Date", each List.Last([End Date]), type nullable date}},GroupKind.Local
)
in
#"Grouped Rows"

Power Query MAX Value from a table

I trying to get the MAX date from a table onto a different date with power query. At the moment I'm stuck and all I get is a table based on a condition. Not sure if this is clear, so I'll explain with the code. This is my code at the moment:
let
Source = Table.NestedJoin(Table.NestedJoin(SKU,{"SKU"},q_UltColh_NEW,{"SKU"},"qUltColh_NEW",JoinKind.LeftOuter),{"SKU"},r_STK,{"SKU"},"Rep_Stk", JoinKind.LeftOuter),
.
.
.
#"Expanded Origem" = ...
#"Expanded Origem" = Table.ExpandTableColumn(#"Merged Queries", "Origem", {"Desc_ORI", "Parent_ORI"}, {"Origem.Desc_ORI", "Origem.Parent_ORI"}),
#"Added Last_Rec" = Table.AddColumn(#"Expanded Origem", "Last_Rec", each
let SKU = [SKU]
in Table.SelectRows(r_GOODSREC,each [SKU]=SKU)
)
in
#"Added Last_Rec"
I have two tables:
SKU Desc
46_24_ ABC
103_5_ DEF
doc_DATE RowNo SKU Cod_ART QTT
10/01/2017 1 46_24_ 46.24 50
14/01/2017 1 46_24_ 46.24 100
14/01/2017 1 103_5_ 103.5 50
16/01/2017 1 103_5_ 103.5 100
And I want to get:
SKU Desc Last_Entry Qtt
46_24_ ABC 14/01/2017 50
103_5_ DEF 16/01/2017 100
my code is returning a table with various columns:
SKU Desc Last_Entry
46_24_ ABC Table
103_5_ DEF Table
I believe once I get the max value I can just exapand the table, unless you tell me that is a bad ideia.
Thank you very much,
I got this with the code below:
Notes:
1. My date format is month/day/year whereas yours was day/month/year.
2. Also, in your question, you show an expected QTT of 50 for SKU 46_24_; but your source table has 100 as the QTT for the latest date of SKU 46_24_, which is why my table has 100 instead of 50.
I used the same two starting tables as you. I called them Table1 and Table2. (Table1 is the one with just the SKU and Desc columns.)
Then I merged those two tables into a new table called Merge1, using a left-outer join.
I guess the key points are:
I used "Group By" (i.e., Table.Group) to group by each SKU and get its max date value in a column I called Last_Entry, and I included all row data in a column I called AllData. Here's the Group By pop-up window:
Then, after the Group By, I expanded the embedded table in AllData and added a new column to flag and filter out the rows where the doc_Date was not equal to Last_Entry.
let
Source = Table.NestedJoin(Table1,{"SKU"},Table2,{"SKU"},"Table2",JoinKind.LeftOuter),
#"Expanded Table2" = Table.ExpandTableColumn(Source, "Table2", {"doc_Date", "RowNo", "SKU", "Cod_ART", "QTT"}, {"doc_Date", "RowNo", "SKU.1", "Cod_ART", "QTT"}),
#"Changed Type" = Table.TransformColumnTypes(#"Expanded Table2",{{"doc_Date", type date}}),
#"Grouped Rows" = Table.Group(#"Changed Type", {"SKU"}, {{"Last_Entry", each List.Max([doc_Date]), type datetime}, {"AllData", each _, type table}}),
#"Expanded AllData1" = Table.ExpandTableColumn(#"Grouped Rows", "AllData", {"Desc", "doc_Date", "QTT"}, {"Desc", "doc_Date", "QTT"}),
#"Added Custom" = Table.AddColumn(#"Expanded AllData1", "Custom", each if[Last_Entry]=[doc_Date] then "Last_Entry" else "NotLast_Entry"),
#"Filtered Rows" = Table.SelectRows(#"Added Custom", each ([Custom] = "Last_Entry")),
#"Removed Columns" = Table.RemoveColumns(#"Filtered Rows",{"Custom", "doc_Date"}),
#"Reordered Columns" = Table.ReorderColumns(#"Removed Columns",{"SKU", "Desc", "Last_Entry", "QTT"})
in
#"Reordered Columns"

Add calculated custom column using entire table for calculation power query or dax

I have this table in Power BI with events concerning some objects
|new_state |object_id | created_at |
|new |1 |11/4/2015 1:50:48 PM |
|in_use |3 |11/4/2015 2:31:10 PM |
|in_use |1 |11/4/2015 2:31:22 PM |
|deleted |2 |11/4/2015 3:14:10 PM |
.....
I am trying to add a calculated column either in DAX or power query so that for each row I would have the previous_state of that object. From a logical point of view it's not difficult: you group by id and for each row in that group you look for the closest previous time and get the "new_state" which would represent the previous state for that row.
I have tried doing this by creating a function in power query and use it in a custom column but I am getting a "cyclic reference detected" error and cannot do it. Any ideas on solutions?
It's hard to express comparisons between rows today in Power Query. Most of the functions assume the table is just an unordered set of rows.
To expand on Oğuz's comment, you could add an index column, then add a column PreviousState indexing into the previous row (or null). As an optimization it might be much faster if you buffer the whole table first.
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WqslLLY8vLkksSVWoyU/KSk0uic9MUahRSC5KBYqlxCeWKNQoxepAFCrUGAKRob6JvpGBoamCoZWpgZWJhUKAL0xNZl58aTHQJGNkZUZWxoZWhgZYlBliKDMyQlKWkpqTCnSDQo0RsjpjK0MThHGxAA==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [Column1 = _t]),
#"Split Column by Delimiter" = Table.SplitColumn(Source,"Column1",Splitter.SplitTextByDelimiter("|", QuoteStyle.Csv),{"Column1.1", "Column1.2", "Column1.3", "Column1.4", "Column1.5"}),
#"Removed Columns" = Table.RemoveColumns(#"Split Column by Delimiter",{"Column1.1", "Column1.5"}),
#"Trimmed Text" = Table.TransformColumns(#"Removed Columns",{},Text.Trim),
#"Promoted Headers" = Table.PromoteHeaders(#"Trimmed Text"),
ChangedType = Table.TransformColumnTypes(#"Promoted Headers",{{"object_id", Int64.Type}, {"created_at", type datetime}, {"new_state", type text}}),
#"Added Index" = Table.AddIndexColumn(ChangedType, "Index", 0, 1),
Buffer = Table.Buffer(#"Added Index"),
#"Added Custom" = Table.AddColumn(Buffer, "PreviousState", each try Buffer{[Index] - 1}[created_at] otherwise null),
#"Inserted Time Subtraction" = Table.AddColumn(#"Added Custom", "TimeDifference", each [created_at] - [PreviousState], type duration)
in
#"Inserted Time Subtraction"
There are surely neater solutions than this but in DAX you can create a calculated column (prevdate) to store the datetime of the previous entry:
=
CALCULATE (
MAX ( [created_at] ),
ALL ( table1 ),
Table1[created_at] < EARLIER ( [created_at] ),
Table1[object_id] = EARLIER ( [object_id] ) )
Then you add another calculated column to store the state at that previous time:
=
CALCULATE (
VALUES ( Table1[new_state] ),
ALL ( Table1 ),
Table1[created_at] = EARLIER ( Table1[prevdate] ),
Table1[object_id] = EARLIER ( Table1[object_id] )
)
I've solved it :D
#"Sorted Rows" = Table.Sort(#"Reordered Columns",{{"object_id", Order.Ascending}, {"created_at", Order.Ascending}}),
#"Added Index" = Table.AddIndexColumn(#"Sorted Rows", "Index", 0, 1),
Buffer = Table.Buffer(#"Added Index"),
#"Added Custom" = Table.AddColumn(Buffer, "PreviousState", each try (if Buffer{[Index] - 1}[object_id]=Buffer{[Index]}[object_id] then Buffer{[Index] - 1}[new_state] else null ) otherwise null)
I'm not sure it's not mostly a hack but it seems to be working. Do you see any point where it might fail in the future?

Resources