有没有更好的方法来按 T-SQL 中的类别开始和结束时间来汇总时间序列?

Is there a better way to summarize a time series by category start and end times in T-SQL?

我想通过以下方式总结时间序列数据:

  1. 类别 -(1.低,2.中等,3.强,4.极端)。
  2. 每个类别 运行 的开始和结束时间。

下图显示了数据片段和所需的输出。

    SELECT.. 
             MIN(ReadingDateTime)
            ,MAX(ReadingDateTime)
    FROM CurrentLogger
    GROUP BY LoggerId
            ,Category
    ORDER BY LoggerId
            ,ReadingDateTime

例如:

我有一种方法,但我相信还有更好的方法。我使用 SQL LAGLEAD 函数标记 运行 类别的开始和结束。

SELECT LoggerId
      ,Location
      ,Category
      ,dBDateTime
      ,FirstInRun = IIF(LAG(dBCategory,1,0) OVER(ORDER BY InstrumentId, dBDateTime)<>dBCategory,1,0)
      ,LastInRun = IIF(LEAD(dBCategory,1,0) OVER(ORDER BY InstrumentId, dBDateTime)<>dBCategory,1,0)
FROM CurrentLogger
ORDER BY InstrumentId 
        ,dBDateTime

输出如下:

有几种丑陋和缓慢的方法可以将其滚动到所需的输出。

我的问题是:

汇总的一种方法是使用 ROW_NUMBER() 函数创建您的组,然后获取每个组的 MIN/MAX 日期。考虑以下因素:

CREATE TABLE #CurrentLogger(LoggerID int, Location varchar(20),Category varchar(20),ReadingDateTime datetime)
INSERT INTO #CurrentLogger VALUES
(10,'OutSide','1. Low','9/14/21 8:16:37 AM'),
(10,'OutSide','1. Low','9/14/21 8:16:39 AM'),
(10,'OutSide','1. Low','9/14/21 8:16:41 AM'),
(10,'OutSide','2. Moderate','9/14/21 8:16:43 AM'),
(10,'OutSide','2. Moderate','9/14/21 8:16:45 AM'),
(10,'OutSide','2. Moderate','9/14/21 8:16:47 AM'),
(10,'OutSide','2. Moderate','9/14/21 8:16:49 AM'),
(10,'OutSide','4. Extreme','9/14/21 8:16:51 AM'),
(10,'OutSide','3. Strong','9/14/21 8:16:53 AM'),
(10,'OutSide','3. Strong','9/14/21 8:16:55 AM'),
(10,'OutSide','3. Strong','9/14/21 8:16:57 AM'),
(10,'OutSide','2. Moderate','9/14/21 8:16:59 AM'),
(10,'OutSide','2. Moderate','9/14/21 8:17:01 AM'),
(10,'OutSide','2. Moderate','9/14/21 8:17:03 AM'),
(10,'OutSide','2. Moderate','9/14/21 8:17:05 AM'),
(10,'OutSide','1. Low','9/14/21 8:17:07 AM'),
(10,'OutSide','1. Low','9/14/21 8:17:09 AM'),
(10,'OutSide','1. Low','9/14/21 8:17:11 AM'),
(10,'OutSide','1. Low','9/14/21 8:17:13 AM'),
(10,'OutSide','1. Low','9/14/21 8:17:15 AM'),
(10,'OutSide','1. Low','9/14/21 8:17:17 AM');

WITH CTE AS
(
    SELECT *,
        ROW_NUMBER() OVER(PARTITION BY LoggerID ORDER BY ReadingDateTime)
        - ROW_NUMBER() OVER(PARTITION BY LoggerID,Location,Category ORDER BY ReadingDateTime) Grp
    FROM #CurrentLogger
)
SELECT LoggerID,Location,Category, MIN(ReadingDateTime) StartDate, MAX(ReadingDateTime) EndDate
FROM CTE
GROUP BY Grp,LoggerID,Location,Category
ORDER BY StartDate