I have a Power BI Desktop file. I am developing a Calculated Table (CT) in DAX language.
I am using a number of manipulations inside to develop this CT (similar to what I do in a T-SQL stored procedure). I have the source as an excel file here.
I develop a number of variables within this DAX query. Ignore any relationships between the tables, since these are variables.
I have the below variable (a table) called VAR_SourceData. Please see the image file below:
It has 4 cities - NYC, LON, LA, SYD. It has 5 different combinations of City-Product.
Each City may have one or more Products.
A combination of a City-Product will have only one unique Quantity (always),
regardless of the year.
For example, SYD and PineApple has 12 as its Quantity always, on the other hand SYD and Grapes has a Quantity of 11 always. (This is regardless of the Year).
A combination of City-Product may or may not have Price for all the years.
For example, LON-Orange has Price for 2020 and 2019 only, on the other hand
LA-Mango has Price for 2019 and 2015 only.
I have a master table (VAR_ReferenceYearLookup) with all the possible years. It has 9 years (2022-2014), in descending order.
I need the desired output of the table VAR_Desired_Output:
I explain the VAR_Desired_Output table as follows:
The table would have every possible combination of City-Product, with a fixed Quantity. The City, Product, Quantity are independent of the Year. However, the Price depends on the Year. If there is no data for Price in a year in the VAR_SourceData table, the VAR_Desired_Output table must show blank.
My desired output must have all the years (2022-2014 (in descending order, preferably)) for every possible combination of City-Product, with the fixed Quantity; the Quantity depends on the City-Product combination, but not on the Year. If the Price for a Year is not available in the VAR_SourceData table, the VAR_Desired_Output table must show blank.
Hence every City-Product combination must have exactly 9 years, with a fixed Quantity always.
I have 5 different combinations of City-Product, hence the VAR_Desired_Output table has 45 rows.
I tried with NATURALINNERJOIN, NATURALLEFTOUTERJOIN, GENERATE etc. But am not able to solve this. I need this as a DAX solution, NOT in Power Query (my table has a number of Calculated Columns).
Can anyone help me achieve my goal?
You can add some power query steps to your table VAR_SourceData to achieve the required output. Try to add these below steps in the Advance Query Editor window of your table-
Note: change the previous step name accordingly in the first below step
let
//your previous existing steps,
#"Added Custom" = Table.AddColumn(#"previous step name", "Custom", each List.Sort(
List.Numbers(
List.Min(VAR_ReferenceYearLookup[Year_LKP]),
List.Max(VAR_ReferenceYearLookup[Year_LKP])
- List.Min(VAR_ReferenceYearLookup[Year_LKP]) + 1
),
Order.Descending
)),
#"Expanded Custom" = Table.ExpandListColumn(#"Added Custom", "Custom"),
#"Added Custom1" = Table.AddColumn(#"Expanded Custom", "Price_new", each if [Year]=[Custom] then [Price] else null),
#"Added Custom2" = Table.AddColumn(#"Added Custom1", "Quantity_new", each if [Year] = [Custom] then [Quantity] else null),
#"Removed Columns" = Table.RemoveColumns(#"Added Custom2",{"Year", "Price", "Quantity"}),
#"Renamed Columns" = Table.RenameColumns(#"Removed Columns",{{"Custom", "Year"}, {"Price_new", "Price"}, {"Quantity_new", "Quantity"}}),
#"Grouped Rows" = Table.Group(#"Renamed Columns", {"City", "Product", "Year"}, {{"Price", each List.Max([Price]), type nullable number}, {"Quantity", each List.Max([Quantity]), type nullable number}})
in
#"Grouped Rows"
Output-
As mentioned, I need a DAX based solution, not in Power Query.
I assume that the 2 variables (VAR_SourceData, VAR_ReferenceYearLookup) are tables, and have this code below:
DesiredOutput_CT =
VAR src = DISTINCT(
SELECTCOLUMNS(
VAR_SourceData,
"City", [City],
"Product", [Product],
"Quantity", [Quantity]
)
)
VAR cj = CROSSJOIN(src, VAR_ReferenceYearLookup)
VAR t1 = SELECTCOLUMNS(
cj,
"Concat", [City] & "-" & [Product] & "-" & [Year_LKP],
"City", [City],
"Product", [Product],
"Quantity", [Quantity],
"Year", [Year_LKP]
)
VAR t2 = SELECTCOLUMNS(
VAR_SourceData,
"Concat", [City] & "-" & [Product] & "-" & [Year],
"Price", [Price]
)
VAR t3 = SELECTCOLUMNS(
t1,
"Concat", [Concat] & "Z",
"City", [City],
"Product", [Product],
"Quantity", [Quantity],
"Year", [Year]
)
VAR t4 = SELECTCOLUMNS(
t2,
"Concat", [Concat] & "Z",
"Price", [Price]
)
VAR t5 = NATURALLEFTOUTERJOIN(t3,t4)
VAR t6 = SELECTCOLUMNS(
t5,
"City", [City],
"Product", [Product],
"Quantity", [Quantity],
"Price", [Price],
"Year", [Year]
)
RETURN t6
Related
bit new to dax and I am struggling in creating a formula.
So I need to write a mathematical calculation which =+(E4+Mx6)/2*33 for the East Silo on the same date and time only.
So the first one would be 07/11/2022 4:30 am calculation (4+4)/2*33
I tried doing the calculation but i couldn't figure out how to calculate based on the same date field
You can do it in Power Query
Mark your Parameter and Value columns
Transform - Pivot them
Add custom column from the new [E4] and [Mx6] columns
M-code should look like this:
#"Pivoted Column" = Table.Pivot(
#"Changed Type", List.Distinct(#"Changed Type"[Parameter]), "Parameter", "Value", List.Sum),
#"Added Custom" = Table.AddColumn(
#"Pivoted Column", "Custom", each ([E4]+[Mx6]) / 2 * 33)
If you want to solve it in DAX, use this measure:
Math =
VAR tbl =
SUMMARIZE(
'Table',
'Table'[Datetime],
'Table'[Silo],
"E4", CALCULATE(
SUM('Table'[Value]),
'Table'[Parameter] = "E4"
),
"Mx6", CALCULATE(
SUM('Table'[Value]),
'Table'[Parameter] = "Mx6"
)
)
RETURN
SUMX(
tbl,
([E4] + [Mx6]) / 2 * 33
)
I have a data set containing:
Accounts selling various fruits in various countries, im working on some metrics and I really want to calculate the time between the first sold fruit in a country to the last sold fruit in the same country.
For instance: "days between" First sold ORANGE in Austria to Last sold ORANGE in AUSTRIA
I have solved this using a measure, which works but this doesn't allow me to work further with it as it throws me error with circular dependicies (ALL reference!)
I wonder if I can do this less complicated? an idea would be to set up an additional table in powerquery having latest date sold by fruit and country similar to what a pivot can do in excel, after that I could link to my main table and retrieve the date by using the RELATED option.
Any ideas?
Current muesure in powerBI:
DURATION =
VAR dispdate =
MIN( 'Test dat'[Dispath] )
VAR lastsoldthiscountry =
CALCULATE(
MAX( 'Test dat'[Last sold date] ),
ALL( 'Test dat' ),
SUMMARIZE( 'Test dat', 'Test dat'[Fruit], 'Test dat'[Country] )
)
RETURN
IF(
NOT ( ISBLANK( lastsoldthiscountry ) ) && NOT ( ISBLANK(dispdate) ),
INT( lastsoldthiscountry - dispdate )
)
Excel raw test:
https://www.dropbox.com/scl/fi/cppyzagm4ahusrxmadlg6/Test_data_withPivot.xlsx?dl=0&rlkey=2nf5wzl7etwr2hqg2lh4oyifx
PBI file:
https://www.dropbox.com/s/ljnyics6d7n74oc/test.pbix?dl=0
If I understand you correctly, you can do what you want entirely in Power Query.
Group by Fruit and Country
Aggregate by Min of Start Date and Max of End Date
Add column to calculate the Days difference:
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{
{"Fruit", type text}, {"Account ID", type text}, {"Country", type text},
{"Sold amount", Int64.Type}, {"Dispath", type date}, {"First sold date", type date}, {"Last sold date", type date}}),
#"Grouped Rows" = Table.Group(#"Changed Type", {"Fruit", "Country"}, {
{"First Date Sold", each List.Min([First sold date]), type nullable date},
{"Last Date Sold", each List.Max([Last sold date]), type nullable date}}),
#"Sorted Rows" = Table.Sort(#"Grouped Rows",{{"Fruit", Order.Ascending}, {"Country", Order.Ascending}}),
#"Added Custom" = Table.AddColumn(#"Sorted Rows", "Days Sold", each
Duration.Days([Last Date Sold]-[First Date Sold]),Int64.Type)
in
#"Added Custom"
The negative number for France Apples seems due to a data entry error
If there is a missing date entry, the table will show a null, due to how PQ processes nulls in arithmetical operations
Please find below links to the Fact table and the overview of all tables. I would like to create a DAX measure, or new column in the Fact table ("transactions"), where:
The currency is NOT equal to EUR (e.g. "BTC"),
Giving the value equal to a opposite value of "amount", as given in the row with EUR as currency (e.g. +5. Positive for negative and vice versa),
Where the date and time of the two rows (EUR and non-EUR) have the same values (e.g. 03/11/2021 and 12:28:06)
The "type" = "trade",
In all other cases, I think it would be best to give a value of 0.
In my Fact table screenshot, I manually added the EUR_amt column in Excel to show what I would like to create
I think it's also possible to add the column, then group by time and date, such that the rows with EUR as currency with EUR_amt being 0, would be removed. All using power query. That would be even better.
(The "Currencies" table just uses the distinct values of the "currency" column in the "transactions" table, via PowerQuery. Not relevant for this question I think)
Many thanks in advance!
-YK
Fact table "transactions"
Overview of tables
Calculated Column:
EUR_amt =
IF (
OR ( transactions[type] <> "trade", transactions[currency] = "EUR" ),
0,
- LOOKUPVALUE (
transactions[amount],
transactions[Date], transactions[Date],
transactions[Time], transactions[Time],
transactions[currency], "EUR",
0
)
)
Here's one way to do this using just Power Query and the Advanced Editor
Group by data and time
Generate a custom column for each subtable based on your rules
Expand the subtables, remove those with "0", and re-order the columns
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"type", type text}, {"currency", type text}, {"Date", type date}, {"Time", type time}, {"amount", type number}}),
//Group by Date and Time
#"Grouped Rows" = Table.Group(#"Changed Type", {"Date", "Time"}, {
//Add the Eur amt column to the grouped table
{"EUR_amt", (t)=>let
//determine relevant euro amt for each sub table
eur= t[amount]{List.PositionOf(t[currency],"EUR")},
//add the column to each subtable basaed on conditions
addCol = Table.AddColumn(t, "EUR_amt",
each if [type]= "trade" and [currency]<>"EUR" then -eur else 0)
in
addCol}}),
//Expand the new table
//Filter out the 0's
//reorder the columns
#"Expanded EUR_amt" = Table.ExpandTableColumn(#"Grouped Rows", "EUR_amt", {"type", "currency", "amount", "EUR_amt"}, {"type", "currency", "amount", "EUR_amt"}),
#"Filtered Rows" = Table.SelectRows(#"Expanded EUR_amt", each ([EUR_amt] <> 0)),
#"Reordered Columns" = Table.ReorderColumns(#"Filtered Rows",{"type", "currency", "Date", "Time", "amount", "EUR_amt"})
in
#"Reordered Columns"
Environment
I have created the two queries in Power Query
"Demo"
let
Source = Table.FromList(List.Random(1000, 20200427),Splitter.SplitByNothing()),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Column1", type text}}),
#"Split Column by Position" = Table.SplitColumn(#"Changed Type", "Column1", Splitter.SplitTextByPositions({0, 5, 7}, false), {"Month", "Amount"}),
#"Changed Type2" = Table.TransformColumnTypes(#"Split Column by Position",{{"Month", type number}, {"Amount", type number}}),
ConvetToMonthNumber = Table.TransformColumns(#"Changed Type2",{{"Month", each Number.RoundDown( 12 * _) + 1, Int64.Type}})
in
ConvetToMonthNumber
and "MockCal"
let
Source = Table.FromList( List.Repeat({1..4},3), Splitter.SplitByNothing(),{"CalQuart"}),
#"Added Index" = Table.AddIndexColumn(Source, "Month", 1, 1)
in
#"Added Index"
and then in the model I have two bits of DAX
Running Amount =
CALCULATE(
SUM('Demo'[Amount]),
FILTER(ALL('Demo'[Month]), 'Demo'[Month] <= MAX('Demo'[Month]))
)
and
WEIRD Run total =
VAR CalcTable = SUMMARIZE(Demo,Demo[Month],"MonthlyRollingAmounts",[Running Amount])
VAR TotalAmount = SUMX(CalcTable,[MonthlyRollingAmounts])
RETURN IF(ISFILTERED(Demo[Month]), [Running Amount], TotalAmount)
With this I can produce the following visual:
This achieves the desired result: Create a measure that sums up its slices by month.
However, when I create a relationship off this table, the SUMX stops working as expected.
The question is: Why does adding this relationship change the behavior of the SUMX? It doesn't seem to me like it should matter at all. Help is appreciated, this one is really bending my brain.
The reason for this is that in your Running Amount measure you remove any filtering on 'Demo'[Month] but this does not propagate upstream to MockCal (which I'm assuming you're using as the first column in your visual).
In general, you want to do your date filtering on your calendar table instead of your fact table. Try this instead:
Running Amount =
CALCULATE(
SUM('Demo'[Amount]),
FILTER(ALL(MockCal), 'MockCal'[Month] <= MAX('MockCal'[Month]))
)
Your WEIRD Run total should be updated as well to use the calendar table.
This snippet displays the chart we are looking at and it has blanks. Instead of blanks for those dates and ID's we want to show what those values are; however, the values(Rates) may not be the same for every ID or Date. (This may happen on rare occasions.)
This snippet displays the data being pulled into Power BI from excel (Just sample data). Notice that all the dates are in order, but notice that some of the ID's do not have entries for certain dates.
I want to be able to say IF(ID is blank per this date, then put Value(Rate) that is attached to this ID).
This may not be possible to do in Power BI. We have an excel spreadsheet with similar data doing what we want but we wanted to automate by using Power BI.
Any Thoughts?
Update
I have got the measures to work in my favor, however; I need to get the total of the measure: Value Or Rate measure. I do have Value Or Rate - visual totals if I can do the same thing as the Value Or Rate measure with a total that would be great.
Please see the updated screen screenshots below.
Visual with fields
Relationships
As a measure, you could do something like below. I'm assuming that you have a model as follows:
Fact: (Date, ID, Value)
DimDate: (Date, ...)
Rates: (ID, Rate)
Dim: (ID, ...)
With these tables you'd have relationships as below:
Dim -1:N-> Fact
Dim <-1:1-> Rates
DimDate -1:N-> Fact
With the model above, you could then build a visual of:
Rows: DimDate[Date]
Columns: Dim[ID]
Values: [Value Or Rate Measure]
Value = SUM ( 'Fact'[Value] )
Rate = SUM ( 'Rates'[Rate] )
Value Or Rate Measure =
VAR Value = [Value]
RETURN
IF ( ISBLANK ( Value ), [Rate], Value )
This might not do what you want for totals - you didn't specify. So if you need visual totals you might try the following:
Value or Rate - visual totals =
SUMX (
CROSSJOIN ( VALUES ( 'Dim'[ID] ), VALUES ( 'DimDate'[Date] ) ),
[Value Or Rate Measure]
)
You could also handle this in Power Query M, assuming you have the same tables I've described above. I'm assuming each table has an associated query of the same name.
let
Source = Table.AddColumn(Dim, "Date", each DimDate[Date]),
#"Expanded Date" = Table.ExpandListColumn(Source, "Date"),
#"Merged Queries" = Table.NestedJoin(#"Expanded Date", {"id", "Date"}, Fact, {"ID", "Date"}, "Fact", JoinKind.LeftOuter),
#"Expanded Fact" = Table.ExpandTableColumn(#"Merged Queries", "Fact", {"Value"}, {"Value"}),
#"Merged Queries1" = Table.NestedJoin(#"Expanded Fact", {"id"}, Rates, {"ID"}, "Rates", JoinKind.LeftOuter),
#"Expanded Rates" = Table.ExpandTableColumn(#"Merged Queries1", "Rates", {"Rate"}, {"Rate"}),
#"Added Custom" = Table.AddColumn(#"Expanded Rates", "Value Or Rate", each if [Value] = null then [Rate] else [Value]),
#"Removed Columns" = Table.RemoveColumns(#"Added Custom",{"Value", "Rate"})
in
#"Removed Columns"
Here, we're doing something similar, but at a table level, instead of as a measure. We crossjoin Dim[ID] and DimDate[Date] to get a dense table of all date and ID combinations. Then we left join the original Fact table and the Rates table. Then we add a column that takes [Value] if it exists, or [Rate] if [Value] is null.