Reputation: 6402
The scope of this quesiton is SQL server 2016.
I have a table with some temperature measurements in. I'm trying to create a CTE with the 3 rows:
First row in the start of the process.
Second row when a threshold temperature is met.
Third row when another threshold temperature is met, but must be after the second row (order by time)
This is my SQL so far. It IS working, but finding the third rows seems a bit clumsy. Isn't there a smarter way to find it.
declare
@ThresholdMinTemp int = 550, @ThresholdCoolingTemp int = 250;
declare @TestData Table
(
Time int,
Temp_Front int,
Temp_Center int,
Temp_Back int
);
insert into @TestData
values
(2, 26, 27, 27),
(102, 26, 27, 27),
(232, 148, 136, 130),
(309, 252, 245, 238),
(548, 549, 553, 550),
(550, 550, 553, 550),
(552, 551, 554, 551),
(555, 552, 555, 552),
(722, 387, 387, 374),
(963, 250, 251, 233),
(967, 248, 249, 231);
with CTE_ResultTable as
(
select ROW_NUMBER() over (order by time) RowNumber, "Description", Time, Temp_Front, Temp_Center, Temp_Back from
(
select top 1 'Start temp' "Description", * from @TestData order by time
union all
select top 1 'ThresholdMinTemp' "Description", * from @TestData where Temp_Front >= @ThresholdMinTemp and Temp_Center >= @ThresholdMinTemp and Temp_Back >= @ThresholdMinTemp order by time
union all
select top 1 'ThresholdCoolingTemp' "Description", * from @TestData where Temp_Front <= @ThresholdCoolingTemp and Temp_Center <= @ThresholdCoolingTemp and Temp_Back <= @ThresholdCoolingTemp
and time > (select top 1 time from TestData1 where Temp_Front >= @ThresholdMinTemp and Temp_Center >= @ThresholdMinTemp and Temp_Back >= @ThresholdMinTemp order by time)
order by time
) Dummy
)
select * from CTE_ResultTable
So in short given the above dataset, I need to find the first row (order by time) where all 3 sensors measures max 250 degrees, after all three have reached 550 degrees!
In my real dataset I have a ID (uniqueidentifier) so if needed it can just be added to the demo dataset.
Upvotes: 1
Views: 98
Reputation: 478
This may help.
declare @TestData Table
(
Time int,
Temp_Front int,
Temp_Center int,
Temp_Back int
);
insert into @TestData
values
(2, 26, 27, 27),
(102, 26, 27, 27),
(232, 148, 136, 130),
(309, 252, 245, 238),
(548, 549, 553, 550),
(550, 550, 553, 550),
(552, 551, 554, 551),
(555, 552, 555, 552),
(722, 387, 387, 374),
(963, 250, 251, 233),
(967, 248, 249, 231);
WITH CTE_ResultTable (seq_no, Description, Time,Temp_Front, Temp_Center,Temp_Back)
AS
(
select top(1) 1 as seq_no, 'Start temp' "Description", Time,Temp_Front, Temp_Center, Temp_Back from @TestData order by time
union all
select top(1) 2 as seq_no, 'ThresholdMinTemp' "Description", Time,Temp_Front, Temp_Center, Temp_Back from @TestData where Temp_Front >= @ThresholdMinTemp and Temp_Center >= @ThresholdMinTemp and Temp_Back >= @ThresholdMinTemp order by time
union all
select top(1) 3 as seq_no, 'ThresholdCoolingTemp' "Description",Time, Temp_Front, Temp_Center, Temp_Back from @TestData where Temp_Back <= @ThresholdCoolingTemp order by time desc
)
select * from CTE_ResultTable
Upvotes: 1
Reputation: 95620
If i understand correctly, this might be a "little" better; it at least doesn't scan the table 3 times (only the once).
WITH KPIs AS(
SELECT *,
CASE WHEN [Time] = MIN(Time) OVER () THEN 'Start Temp'
WHEN Temp_Front >= @ThresholdMinTemp AND Temp_Center >= @ThresholdMinTemp AND Temp_Back >= @ThresholdMinTemp THEN 'ThresholdMinTemp'
WHEN Temp_Front <= @ThresholdCoolingTemp AND Temp_Center <= @ThresholdCoolingTemp AND Temp_Back <= @ThresholdCoolingTemp
AND COUNT(CASE WHEN Temp_Front >= @ThresholdMinTemp AND Temp_Center >= @ThresholdMinTemp AND Temp_Back >= @ThresholdMinTemp THEN 1 END) OVER (ORDER BY [Time] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) > 1 THEN 'ThresholdCoolingTemp' END AS KPI
FROM @TestData),
RNs AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY KPI ORDER BY [time] ASC) AS RN
FROM KPIs)
SELECT ROW_NUMBER() OVER (ORDER BY [Time]) AS RowNumber,
KPI AS [Description],
[Time],
Temp_Front, Temp_Center, Temp_Back
FROM RNs
WHERE KPI IS NOT NULL
AND RN = 1
ORDER BY RowNumber ASC;
Upvotes: 1