3

IDと位置の表があります

CREATE TABLE #MissingSequence (ID INT NOT NULL, Position INT NOT NULL)
INSERT INTO #MissingSequence (ID,Position)
SELECT 36,1
UNION ALL SELECT 36,2
UNION ALL SELECT 36,3
UNION ALL SELECT 36,4
UNION ALL SELECT 36,5
UNION ALL SELECT 36,6
UNION ALL SELECT 44,1
UNION ALL SELECT 44,3
UNION ALL SELECT 44,4
UNION ALL SELECT 44,5
UNION ALL SELECT 44,6

私が見つけようとしているのは、IDによるポジションのシーケンスにブレークがあるかどうかです。この場合、44,1と44,3の間のブレークです。

私はなんとか一緒に解析することができました:

SELECT  l.ID
    ,Start_Position = MIN(l.Position) + 1
    ,Stop_Position = MIN(fr.Position) - 1
FROM #MissingSequence l
LEFT JOIN #MissingSequence r 
    ON l.Position = r.Position - 1
LEFT JOIN #MissingSequence fr 
    ON l.Position < fr.Position
WHERE r.Position IS NULL
    AND fr.Position IS NOT NULL
GROUP BY l.ID

ただし、ID値が複数ある場合は機能しません。IDが1つだけの場合は機能します(44)。

考え、コメント、提案?

ありがとう!

4

3 に答える 3

8

左の自己結合は良い本能でしたが、集約がそれをカットするとは思いません。確かに、自己結合に matching-ID 句を含める必要があります。

null-left-join のアイデアを使用し、一番上の行と一番下の行を選択し、それらの間に何もないことを確認する (ANSI 準拠の) バージョンを次に示します。

SELECT
    above.ID AS ID, below.Position+1 AS Start_Position, above.Position-1 AS End_Position
FROM MissingSequence AS above
JOIN MissingSequence AS below
    ON below.ID=above.ID AND below.Position<above.Position-1
LEFT JOIN MissingSequence AS inbetween
    ON inbetween.ID=below.ID AND inbetween.Position BETWEEN below.Position+1 AND above.Position-1
WHERE inbetween.ID IS NULL;

+----+----------------+--------------+
| ID | Start_Position | End_Position |
+----+----------------+--------------+
| 44 |              2 |            2 | 
+----+----------------+--------------+
于 2009-04-07T20:31:46.760 に答える