如何通过考虑与以前的原始数据相同的列中的数据来对 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
实际开始/结束时间列表示指令 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