18

ID列のあるテーブルと番号のある別の列があります。1つのIDに複数の番号を含めることができます。例えば

ID | Number
 1 |  25
 1 |  26
 1 |  30
 1 |  24
 2 |  4
 2 |  8
 2 |  5

このデータに基づいて、新しいテーブルにこれを入れたい

ID | Low | High 
1  |  24 |  26
1  |  30 |  30
2  |  4  |  5
2  |  8  |  8

ご覧のとおり、24、25、26のように、数字が連続しているデータをマージしたいと思います。したがって、現在、最低値は24、最高値は26、そして30はまだ別の範囲です。私は大量のデータを扱っているので、パフォーマンスのためにカーソルを使用したくないです(これは以前行っていたものであり、物事をかなり遅くしていました)...これを達成するための最良の方法は何ですか?私はSQLのプロではないので、これを簡単にすることができる関数があるかどうか、またはこれを達成するための最速の方法が何であるかはわかりません。

助けてくれてありがとう。

4

4 に答える 4

36

重要な観察事項は、数列から別の数列を差し引いたものは定数であるということです。を使用して別のシーケンスを生成できますrow_number。これにより、すべてのグループが識別されます。

select id, MIN(number) as low, MAX(number) as high
from (select t.*,
             (number - ROW_NUMBER() over (partition by id order by number) ) as groupnum
      from t
     ) t
group by id, groupnum

残りは単なる集計です。

于 2013-01-02T16:24:34.170 に答える
3

CTE と再帰を使用したソリューション:

WITH CTE AS (
  SELECT T.ID, T.NUMBER, T.NUMBER AS GRP
  FROM T 
  LEFT OUTER JOIN T T2 ON T.ID = T2.ID AND T.NUMBER -1 = T2.NUMBER 
  WHERE T2.ID IS NULL
  UNION  ALL
  SELECT T.ID, T.NUMBER, GRP
  FROM CTE 
  INNER JOIN T
  ON T.ID = CTE.ID AND T.NUMBER  = CTE.NUMBER + 1
)
SELECT ID, MAX( NUMBER ), MIN(NUMBER)
FROM CTE
GROUP BY ID, GRP

fiddlesql での結果

于 2013-01-02T16:27:57.007 に答える
0

カーソルの代わりにテーブル変数WHILEでループ構造を使用することをお勧めします。

例えば、

DECLARE @TableVariable TABLE
(
    MyID int IDENTITY (1, 1) PRIMARY KEY NOT NULL,
    [ID] int,
    [Number] int
)

DECLARE @Count int, @Max int

INSERT INTO @TableVariable (ID, Number)
SELECT ID, Number
FROM YourSourceTable

SELECT @Count = 1, @Max = MAX(MyID)
FROM @TableVariable

WHILE @Count <= @Max
BEGIN

    ...do your processing here...


    SET @Count = @Count + 1

END
于 2013-01-02T16:26:37.693 に答える