有没有更好的方法来按 T-SQL 中的类别开始和结束时间来汇总时间序列?
Is there a better way to summarize a time series by category start and end times in T-SQL?
我想通过以下方式总结时间序列数据:
- 类别 -(1.低,2.中等,3.强,4.极端)。
- 每个类别 运行 的开始和结束时间。
下图显示了数据片段和所需的输出。
由于 Categories
(1. 低,2. 中等,3. 强,4. 极端)在整个时间线中重复,因此下面的 SELECT
方法将在四行中汇总整个 table 的 MIN
和 MAX
ReadingDateTime
值。
- 低类别中所有读数的最小值和最大值
ReadingDateTime
。
- 中等类别中所有读数的最小值和最大值
ReadingDateTime
。
- 强类别中所有读数的最小值和最大值
ReadingDateTime
。
- 极端类别中所有读数的最小值和最大值
ReadingDateTime
。
SELECT..
MIN(ReadingDateTime)
,MAX(ReadingDateTime)
FROM CurrentLogger
GROUP BY LoggerId
,Category
ORDER BY LoggerId
,ReadingDateTime
例如:
我有一种方法,但我相信还有更好的方法。我使用 SQL LAG
和 LEAD
函数标记 运行 类别的开始和结束。
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
我想通过以下方式总结时间序列数据:
- 类别 -(1.低,2.中等,3.强,4.极端)。
- 每个类别 运行 的开始和结束时间。
下图显示了数据片段和所需的输出。
由于
Categories
(1. 低,2. 中等,3. 强,4. 极端)在整个时间线中重复,因此下面的SELECT
方法将在四行中汇总整个 table 的MIN
和MAX
ReadingDateTime
值。- 低类别中所有读数的最小值和最大值
ReadingDateTime
。 - 中等类别中所有读数的最小值和最大值
ReadingDateTime
。 - 强类别中所有读数的最小值和最大值
ReadingDateTime
。 - 极端类别中所有读数的最小值和最大值
ReadingDateTime
。
- 低类别中所有读数的最小值和最大值
SELECT..
MIN(ReadingDateTime)
,MAX(ReadingDateTime)
FROM CurrentLogger
GROUP BY LoggerId
,Category
ORDER BY LoggerId
,ReadingDateTime
例如:
我有一种方法,但我相信还有更好的方法。我使用 SQL LAG
和 LEAD
函数标记 运行 类别的开始和结束。
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