如何通过考虑与以前的原始数据相同的列中的数据来对 sql table 进行分组

How to group sql table by considering data in the same column as per previous raw data

实际开始/结束时间列表示指令 start/end 日期。

但真正的指令会继续进行,直到 Min、Aim 或 Max 都发生变化。

所以,我需要根据最小目标和最大组对原始数据进行分组。

我不能直接使用它们作为group by,因为3个月前和这个月可以有相同的Min-Aim-Max。

Name ActualStartTime ActualEndTime FLOW_SUM LIMS_AVG Min Aim Max
DOI 10:15:25.793 18:30:53.027 5884 148 140 155 160
DOI 18:30:53.027 01:14:50.177 2170 149 140 155 160
DOI 01:14:50.177 11:18:58.383 3008 148 140 145 150

例如截图中; 行号 1,2 在同一指令中,需要求和 flow_sum 并取平均值 lims_avg 第 3 行本身就是一条指令 第4、5、6、7行是一条指令

不知何故,在按如下方式订购后,我需要与之前的 1 个 raw 建立关系,然后再与另一个 raw 建立关系,直到找到不同的 tripple Min-Aim_Max。

我该如何查询?

这是一种空岛问题。

解决方法有很多,这里是一个:

  • 使用LAG
  • 计算每个岛的起点
  • 使用窗口化 COUNT
  • 为每个岛屿分配一个组 ID
  • 按组 ID 分组,return 聚合
WITH StartPoints AS (
    SELECT *,
      IsStart = CASE WHEN
            LAG(dc.Min) OVER (PARTITION BY dc.Name ORDER BY dc.ActualStartTime) = dc.Min
        AND LAG(dc.Aim) OVER (PARTITION BY dc.Name ORDER BY dc.ActualStartTime) = dc.Aim
        AND LAG(dc.Max) OVER (PARTITION BY dc.Name ORDER BY dc.ActualStartTime) = dc.Max
        THEN NULL ELSE 1 END
    FROM dbo.vw_DOI_DEVIATION_CONSISTENCY dc
),
Groupings AS (
    SELECT *,
      GroupId = COUNT(dc.IsStart) OVER (PARTITION BY dc.Name ORDER BY dc.ActualStartTime ROWS UNBOUNDED PRECEDING)
    FROM StartPoints dc
)
SELECT
  dc.Name
  StartTime = MIN(dc.ActualStartTime),
  EndTime =   MAX(dc.ActualEndTime
  FLOW_SUM =  SUM(dc.FLOW_SUM),
  LIMS_AVG =  AVG(dc.LIMS_AVG),
  Min =       MIN(dc.Min),
  Aim =       MIN(dc.Aim),
  Max =       MIN(dc.Max)
FROM Groupings dc
GROUP BY dc.Name, dc.GroupId;

我不确定这是否有帮助,但现在没有更多时间。我希望它能对您有所帮助:

DECLARE @Table TABLE    
        (
                ActualStartTime     datetime
            ,   AimMin              int
            ,   AimCurrent          int
            ,   AimMax              int
        )   
;
INSERT INTO @Table
    VALUES  
    
    ('2020-12-31 10:15',    140,    155,    160)
,   ('2021-01-01 18:30',    140,    155,    160)
,   ('2021-01-02 01:14',    140,    145,    150) 
,   ('2021-01-02 11:18',    135,    140,    150)
,   ('2021-01-04 10:47',    135,    140,    150) 
,   ('2021-01-05 09:54',    135,    140,    150)
,   ('2021-01-05 16:36',    135,    140,    150) 
,   ('2021-01-05 19:33',    140,    155,    160)
,   ('2021-01-05 23:49',    140,    155,    160) 
,   ('2021-01-06 20:06',    140,    155,    160)
,   ('2021-01-07 10:32',    140,    155,    160) 
,   ('2021-01-07 16:53',    140,    155,    160)
,   ('2021-01-08 09:54',    140,    160,    160) 
;

;WITH Table1 AS
    (
        SELECT  TOP 100 PERCENT
                RowNo = RANK() OVER(PARTITION BY AimMin, AimCurrent, AimMax ORDER BY ActualStartTime)
            ,   *
        FROM    @Table
        ORDER BY ActualStartTime
    )
,   Table2  AS
    (
        SELECT  TOP 100 PERCENT
                RowNo = RANK() OVER(PARTITION BY AimMin, AimCurrent, AimMax ORDER BY ActualStartTime)
            ,   *
        FROM    @Table
        ORDER BY ActualStartTime
    )


SELECT  DISTINCT
        T1.* 
FROM    Table1  T1
JOIN    Table2  T2  ON T2.RowNo = T1.RowNo+1
WHERE   T2.RowNo = 3
    AND DATEDIFF(DAY,T1.ActualStartTime, T2.ActualStartTime) BETWEEN 0 AND 2
ORDER BY T1.ActualStartTime