在另一行之后找到一行

时间:2018-05-02 09:21:43

标签: sql sql-server sql-server-2016

此问题的范围是SQL server 2016.

我有一张表有一些温度测量值。我试图创建一个包含3行的CTE:

流程开始的第一行。

满足阈值温度时的第二行。

满足另一个阈值温度时的第三行,但必须在第二行之后(按时间顺序)

到目前为止,这是我的SQL。它正在工作,但找到第三行似乎有点笨拙。难道没有一种更聪明的方法可以找到它。

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

所以简而言之,考虑到上面的数据集,我需要找到第一行(按时间排序),其中所有3个传感器测量最大250度,然后三个都达到550度!

在我的真实数据集中,我有一个ID(uniqueidentifier),因此如果需要,它可以添加到演示数据集中。

2 个答案:

答案 0 :(得分:1)

如果我理解正确,这可能是一个小小的&#34;更好;它至少不会扫描表3次(只有一次)。

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;

答案 1 :(得分:1)

这可能有所帮助。

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