0

助けてください、私は私のMSSQLデータテーブルの1つに次のデータを持っています。

ID | StartDateTime | EndDateTime | OrderNo |
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が複数回使用されているかどうかを判断する方法がないことです。Order6001が2回実行されたとは言えません。

今後、注文の各実行を一意に識別するための新しいフィールドを追加できるようにしたいと思います。ただし、以前のレコードに戻って更新することもできます。

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でグループ化できるという考えで、以下を受け取ります。

OrderNo | Run | RunStart | RunEnd |
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、カーソルなどを使用してデータを実行する複数の方法を試しました。簡単な解決策があると思いますが、理解できません。

これが理にかなっていることを願っています。

編集

最初のラウンドには含めなかった追加の複雑さを参照するようにデータテーブルを変更しました。提供されたアーロンのソリューションはうまく機能したでしょう。ただし、実行は最大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 に答える