0

请帮忙,我的一个 MSSQL 数据表中有以下数据。

ID |开始日期时间 |结束日期时间 |订单号|
1 |12-08-01 08:00 |12-08-01 08:00 |6001 |
5 |12-08-01 09:00 |12-08-01 10:00 |6001 |
7 |12-08-01 10:00 |12-08-01 11:00 |6001 |
10 |12-08-01 11:00 |12-08-01 12:00 |6002 |
15 |12-08-01 12:00 |12-08-01 13:00 |6002 |
22 |12-08-01 13:00 |12-08-01 14:00 |6003 |
29 |12-08-01 14:00 |12-08-01 15:00 |6001 |
33 |12-08-01 15:00 |12-08-01 16:00 |6001 |
36 |12-08-01 16:00 |12-08-01 17:00 |6004 |

问题是目前我无法判断 OrderNo 是否已被多次使用。我不能说订单 6001 已经运行了两次。

从现在开始,我希望能够添加一个新字段来唯一标识每次运行的订单。但也可以回顾以前的记录并更新它们。

ID |StartDateTime |EndDateTime |OrderNo|Run|
1 |12-08-01 08:00 |12-08-01 08:00 |6001 |1 |
5 |12-08-01 09:00 |12-08-01 10:00 |6001 |1 |
7 |12-08-01 10:00 |12-08-01 11:00 |6001 |1 |
10 |12-08-01 11:00 |12-08-01 12:00 |6002 |1 |
15 |12-08-01 12:00 |12-08-01 13:00 |6002 |1 |
22 |12-08-01 13:00 |12-08-01 14:00 |6003 |1 |
29 |12-08-01 14:00 |12-08-01 15:00 |6001 |2 |
33 |12-08-01 15:00 |12-08-01 16:00 |6001 |2 |
36 |12-08-01 16:00 |12-08-01 17:00 |6004 |1 |

这个想法是我可以按 OrderNo 和 Run 分组,并将收到以下内容。

订单号 |运行 |运行开始 |运行结束 |
6001 | 1 |12-08-01 08:00 |12-08-01 11:00 |
6001 | 2 |12-08-01 14:00 |12-08-01 16:00 |
6002 | 1 |12-08-01 11:00 |12-08-01 13:00 |
6003 | 1 |12-08-01 13:00 |12-08-01 14:00 |
6004 | 1 |12-08-01 16:00 |12-08-01 17:00 |

我尝试了多种方法使用 ROW_NUMBER、CTE、游标等来运行数据。我觉得有一个简单的解决方案,但我无法弄清楚。

我希望这是有道理的。

编辑

我已经更改了数据表以引用一个额外的并发症,我第一次没有包括在内。Aaron 提供的解决方案可以正常工作。但它假设运行最多只能持续 2 小时(或行)。在我的数据库中,这些运行 n 小时(或行)。对不起,我第一次不清楚,我感谢迄今为止提供的帮助。

4

1 回答 1

1

您的编辑实际上使问题对我来说更简单(可能只是因为我最初错过了一个更简单的岛屿方法)。

;WITH x AS 
(
  SELECT OrderNo, StartDateTime, EndDateTime,
    rn1 = ROW_NUMBER() OVER (ORDER BY StartDateTime), 
    rn = ROW_NUMBER() OVER (PARTITION BY OrderNo ORDER BY StartDateTIme)
  FROM dbo.table_name -- you need to change this
),
y AS
(
  SELECT OrderNo, Island = rn1 - rn, 
    rs = MIN(StartDateTime), 
    re = MAX(EndDateTime) 
  FROM x GROUP BY OrderNo, rn1 - rn
)
SELECT 
  OrderNo, 
  Run = ROW_NUMBER() OVER (PARTITION BY OrderNo ORDER BY rs),
  RunStart = rs, 
  RunEnd = rs
FROM y
ORDER BY OrderNo, Run;

把我原来的答案留给后代。


可能有一种更简单的方法,但这会得到您使用窗口函数后的答案。

;WITH x AS 
(
  SELECT ID, StartDateTime, EndDateTime, OrderNo,
    rn = ROW_NUMBER() OVER (PARTITION BY OrderNo ORDER BY StartDateTime) 
  FROM dbo.table_name -- you need to change this
), y AS
(
  SELECT x.ID, x.StartDateTime, x.EndDateTime, x.OrderNo, x.rn,
      x2ID = x2.ID, x2S = x2.StartDateTime, x2E = x2.EndDateTime, 
      x2O = x2.OrderNo, x2rn = x2.rn
  FROM x LEFT OUTER JOIN x AS x2
  ON x.OrderNo = x2.OrderNo
  AND x.rn = x2.rn - 1
  AND x.ID = x2.ID - 1
)
SELECT 
  OrderNo, 
  Run = ROW_NUMBER() OVER (PARTITION BY OrderNo ORDER BY StartDateTime),
  RunStart = StartDateTime, 
  RunEnd = COALESCE(x2E, EndDateTime) 
FROM y
WHERE x2ID IS NOT NULL 
OR NOT EXISTS 
(
  SELECT 1 FROM y AS y2 WHERE y2.OrderNo = y.OrderNo AND y2.x2rn = y.rn
)
ORDER BY OrderNo, Run;
于 2012-08-20T16:35:21.473 回答