CTE output to different column names - common-table-expression

I am trying to retrieve first and last prices (costs) paid for items and have the prices, dates, and part numbers displayed like this...
Part Number
FirstDate
FirstCost
LastDate
LastCost
The Part Number, FirstDate, and LastDate are located in a View (ViewPurchParts06611). I need to create a CTE (I assume) to use this data to extract the associated costs from a table (PODet).
Here is what I have so far...
IF OBJECT_ID (N'dbo.PurchParts06611PH', N'U') IS NOT NULL
DROP TABLE PTD.dbo.PurchParts06611PH;
GO
CREATE TABLE PTD.dbo.PurchParts06611PH (SubPartNo varchar(200), FirstDate datetime, UnitCost float);
WITH FirstCostCTE AS
(
SELECT ViewPurch06611Dates.SubPartNo, ViewPurch06611Dates.FirstDate, PODet.UnitCost AS First_Cost
FROM ViewPurch06611Dates
LEFT JOIN PODet ON (ViewPurch06611Dates.FirstDate = PODet.DueDate) AND (ViewPurch06611Dates.SubPartNo = PODet.PartNo)
WHERE PODet.DueDate > '2019-01-01'
UNION ALL
SELECT ViewPurch06611Dates.SubPartNo, ViewPurch06611Dates.LastDate, PODet.UnitCost AS Last_Cost
FROM ViewPurch06611Dates
LEFT JOIN PODet ON (ViewPurch06611Dates.LastDate = PODet.DueDate) AND (ViewPurch06611Dates.SubPartNo = PODet.PartNo)
)
INSERT INTO PTD.dbo.PurchParts06611PH(E1.SubPartNo, E1.FirstDate, E1.UnitCost)
SELECT DISTINCT E1.SubPartNo, E1.FirstDate, E1.First_Cost
FROM FirstCostCTE E1
LEFT JOIN FirstCostCTE E2
ON E1.SubPartNo = E2.SubPartNo
It outputs the following...
Part Number
FirstDate
FirstCost
LastDate
LastCost
4535-670-03511-RM1
2019-01-10 00:00:00.000
30
4535-670-03511-RM1
2022-08-19 00:00:00.000
13.25
4535-670-03511-RM2
2019-01-10 00:00:00.000
9
4535-670-03511-RM2
2022-08-19 00:00:00.000
3.25
4535-670-03511-RM3
2019-01-10 00:00:00.000
12
4535-670-03511-RM5
2020-11-17 00:00:00.000
16.3
4535-670-03521-RM
2020-01-24 00:00:00.000
43.48
4535-670-03521-RM
2022-07-18 00:00:00.000
48.85
4535-670-03531-RM
2019-01-23 00:00:00.000
44.73
4535-670-03531-RM
2022-04-15 00:00:00.000
59.22
4535-670-04471-RM
2019-01-24 00:00:00.000
28
4535-670-04471-RM
2020-10-30 00:00:00.000
24.56
The first instance of the part number is showing the FirstDate and FirstCost, however, the second instance of the part number is showing the LastDate and LastCost. Obviously, this is not the formatting I want to produce. I want the LastDate and LastCost values to display in their own columns for each part number.
Can anyone point me in the right direction and make sense of my crazy code so far and where I am going wrong?

Related

Power BI count null rows

I have two columns. Both have a general key INT value called TicketId, but one table has less TicketIds than another table. Both tables have different quantity of columns, so =EXCEPT() formula wouldn't fit.
For example, the current counting of rows looks like this:
Dates
Tab1
Tab2
08.11.2022
1058
950
09.11.2022
1058
1056
22.11.2022
2342
302
I am looking for a DAX measure forluma that will calculate TicketIds that exist in Tab1, but doesn't exist in Tab2. It should be not a formula like 1058 - 950 = 108. Because after there will be drillthrough to show all the TicketIds that were calculated (exist in Tab1 and doesn't exist in Tab2).
Dates
Tab1
Tab2
Tabcross
08.11.2022
1058
950
108
09.11.2022
1058
1056
2
22.11.2022
2342
302
2040
Let's say you have a model like this:
and your datasets like this:
Define your measures like this:
OnlyTable1 = COUNTROWS(VALUES(table1[TicketId]))
OnlyTable2 = COUNTROWS(VALUES(table2[TicketId]))
ID_Difference = COUNTROWS(EXCEPT(
VALUES(table1[TicketId]),
VALUES(table2[TicketId])
))
Then if we put it on a table visual:
Here is how to apply EXCEPT() to your problem:
TabDiff =
EXCEPT (
VALUES ( Tab1[TicketId] ),
VALUES ( Tab2[TicketId] )
)
Note that this creates a calculated table.

Calculate age cluster dynamically in DAX - Power BI

I have created a report for the HR department. One of the visuals aims to display the pyramid of ages of the employees by gender (we take cluster of 5 years, e.g. 20-25 for people between 20 and 25 years old).
To make it simple, data wise, I have a table with the list of employees, including their date of birth and many other fields, not relevant for this post. I added a calculated column with the age cluster based on the today’s date:
AgeCluster =
VAR AgeCalc=if(HR_DATA[Birthdate]=blank(),blank(),DATEDIFF(HR_DATA[Birthdate],today(),YEAR))
VAR Mult5=INT(AgeCalc/5)
RETURN
if(isblank(AgeCalc),blank(),5*Mult5&"-"&5*(Mult5+1))
And I have a basic visual (tornado chart with the AgeCluster in Group, showing male and female)
Now my issue is that my report should be dynamic, so the user should be able to see the situation in the past or in the future... I have a calendar table (not linked to my HR_Data table), and a date slicer on my report's page. I need the age cluster to be recalculated.
I have tried a calculated table, but I can’t get it working properly. I have read various blog posts on similar issue, but still can't figure out how to solve it...
Any idea or tips much appreciated.
Thank you so much!
Dynamic filtering usually means in these situations that you need a fixed x-axis to work with. That x-axis is calculated outside the original table, such as a parameter table.
Assuming your data looks like this:
Table: Employees
EmployeeID
DOB
1
20 March 1977
2
05 December 1981
3
25 December 1951
4
20 December 1954
5
04 March 1980
6
24 July 1968
7
07 June 1984
8
01 October 1992
9
25 February 1999
10
02 November 1987
First, we need to create the Age Groups with their respective lower and top bands. This table uses a similar code when a parameter table is created.
Table: Buckets
Because you are using whole numbers, I think is best to calculate the TopBand by adding 4. In that case, you don't have repeating numbers. In other words, ranges shouldn't overlap (20-25 and 25-30)
Buckets =
SELECTCOLUMNS (
GENERATESERIES ( 20, 80, 5 ),
"Age Series",
[Value] & " - " & [Value] + 4,
"LowerBand", [Value],
"TopBand", [Value] + 4
)
Also, we will need a Calendar Table to filter accordingly.
Table: CalendarHR
CalendarHR =
ADDCOLUMNS (
CALENDAR ( MIN ( Employees[DOB] ), TODAY () ),
"Year", YEAR ( [Date] )
)
With all that, you can create a calculation that can be filter dynamically.
DAX Measure:
EmployeesbyBracket =
VAR _SelectedDate =
MAX ( CalendarHR[Date] )
VAR _SelectedLowerBand =
SELECTEDVALUE ( Buckets[LowerBand] )
VAR _SelectedTopBand =
SELECTEDVALUE ( Buckets[TopBand] )
VAR EmployeesAge =
ADDCOLUMNS (
Employees,
"Age",
INT ( DATEDIFF ( [DOB], _SelectedDate, YEAR ) / 5 ) * 5
)
RETURN
COUNTROWS (
FILTER (
EmployeesAge,
[Age] >= _SelectedLowerBand
&& [Age] <= _SelectedTopBand
)
)
Output
I've created a table visual with the Age Groups from the Buckets table.
Both a calculated column and a calculated table will be static and not achieve your desired objective. You need age to be calculated via a measure.
Create a disconnected table with your age buckets and then implement the dynamic segmentation pattern.

DAX Cycle Time at column level which can then be AVERAGE'd up (Parameter is not the correct type)

I'm trying to calculate cycle times at row level, based on two slicers. Which I can then use in a measure to get Averages e.g. per client.
I have two pre-populated tables
CycleStartDateOptions
Id StartDateName
1 [Incident Date]
2 [Examination Date]
CycleEndDateOptions
Id StartDateName
3 [Resolution Date]
4 [Closed Date]
Then a measure on CycleStartDateOptions
SelectedCycleStartDate = SELECTEDVALUE(CycleStartDateOptions[Id])
.. and CycleEndDateOptions
SelectedCycleEndDate = SELECTEDVALUE(CycleEndDateOptions[Id])
Example MainTable Data:
ClientID [IncidentId] [Incident Date] [Examination Date] [Resolution Date] [Closed Date]
C0001 I00001 2020-01-01 2020-02-01 2020-03-01 2020-04-01
C0001 I00002 2020-01-01 2020-03-01 2020-04-01 2020-05-01
C0002 I00003 2021-01-02 2021-02-02 2021-03-02 2020-04-02
C0002 I00004 2021-01-02 2021-03-02 2021-04-02 2020-05-02
I have two measures on MainTable:
CycleStartDateSwitch = SWITCH(CycleStartDateOptions[SelectedCycleStartDate],
1,MIN('MainTable'[Incident Date]),
2,MIN('MainTable'[Examination Date]))
CycleEndDateSwitch = SWITCH(CycleEndDateOptions[SelectedCycleEndDate],
3,MIN('MainTable'[Resolution Date]),
4,MIN('MainTable'[Closed Date]))
Finally to generate my dynamic cycle time, I have this measure:
CycleTimeDynamic = DATEDIFF('MainTable'[CycleStartDateSwitch], 'MainTable'[CycleEndDateSwitch], DAY)
Phew! This works when shown in a table and for each incident I see a value for Cycle Time between the user selected start and end dates e.g. Incident Date to Resolution Date.
The problem now is, the above is done as measures. But I need to be able to filter on date ranges e.g. Incident Date > 2020-01-01 and 2022-01-01 and get Average cycle times per client. When I try to create a new measure it underlines my CycleTimeDynamic measure and says "Parameter is not the correct type".
I tried doing the CycleStartDateSwitch and CycleEndDateSwitch as Columns using e.g.
CycleStartDateSwitch = SWITCH(CycleStartDateOptions[SelectedCycleStartDate],
1,'MainTable'[Incident Date],
2,'MainTable'[Examination Date])
.. but it won't surface any data.
Any ideas what I'm doing wrong? This would be easy in SQL and I'm sure it's doable in DAX but I'm struggling with what should be Columns and Measures.
What I want to be able to see:
ClientID [Incident Count] [Average Cycle Time]
C0001 5 123
C0002 8 345
Any help much appreciated!

Power Bi Super slow Query needs a performance boost

Our Subscription table is contains around 40k entries. I am trying to calculate the Monthly-Recurring.Dim is a simple calendar table to map the date ranges start and end to the days.
Sumx('Subscription Clean',
CALCULATE(
SUMX(
SUMMARIZE(
FILTER(
CROSSJOIN(
'Subscription Clean',Dim
),
Dim[Date] <= 'Subscription Clean'[End At] &&
Dim[Date] > 'Subscription Clean'[Start At]
),
'Subscription Clean'[Duration total],
'Subscription Clean'[Duration],
'Subscription Clean'[End At],
'Subscription Clean'[Start At],
'Subscription Clean'[Price]),
DIVIDE(DIVIDE(
'Subscription Clean'[Price],DATEDIFF([Start At],[End At],DAY)+1
),1.19) % Tax of 19
)
)
)
The data looks like this
Sales Id
Product name
created At
end at
Cancelled At
Price in €
Duration
1
bananas
01.01.2021
01.03.2021
28.02.2021
20.00
2
2
apples
01.02.2021
01.05.2021
null
90€
3
The output should be like this for the mmr each month 10€ come from the first position for the months {1,2}
Each price will be distributed between the dates Start and End.
jan = 10
feb = 40
mar = 30
apr = 30
may = 0
The DAX query is working properly but hell a slow. Is there any way to improve the performance? Further the calculated measure will be used to do more calculations and needed to be loaded in memory if possible for quick access. Maybe anyone knows how to do it properly and I can leech some good hints ;)

Calculate monthly value between 2 tables without an explicit relationship in Power BI model

I am trying to create a measure that calculates (a/qty)*100 for each month,
where qty commes from Delivery table (generated with an R script)
month qty
<date> <dbl>
1 2019-02-01 1
2 2019-03-01 162
3 2019-04-01 2142
4 2019-05-01 719
And a comes from a table TABLE_A that has been created within Power BI that looks like this :
Client Date a
x 2019-03-07 3
x 2019-04-14 7
y 2019-03-12 2
So far, I managed to calculate that value overall with the following measure formula :
MEASURE = CALCULATE( (Sum(TABLE_A[a])/sum(Delivery[qty]))*100)
The issue I have is that I would need this measure monthly (i.e. join the tables on month) without explicitly defining a link between the tables in the PowerBI model.
For each row in TABLE_A you need to look up the corresponding qty in Delivery, so try something along these lines:
MEASURE =
DIVIDE(
SUM( TABLE_A[a] ),
SUMX(
TABLE_A,
LOOKUPVALUE(
Delivery[qty],
Delivery[month], EOMONTH( TABLE_A[Date], -1 ) + 1
)
)
) * 100
The formula EOMONTH( TABLE_A[Date], -1 ) returns the end of the previous month relative to that date and adding 1 day to that to get the start of the current month for that date.