Vous pouvez utiliser la requête suivante enveloppée dans un CTE
afin d'attribuer des numéros de séquence aux valeurs contenues dans votre séquence :
;WITH Seq AS (
SELECT v, ROW_NUMBER() OVER(ORDER BY k) AS rn
FROM (VALUES(1, 5), (2, 9), (3, 6)) x(k,v)
)
Sortie :
v rn
-------
5 1
9 2
6 3
Utilisation du CTE
ci-dessus vous pouvez identifier des îlots, c'est-à-dire des tranches de lignes séquentielles contenant l'intégralité de la séquence :
;WITH Seq AS (
SELECT v, ROW_NUMBER() OVER(ORDER BY k) AS rn
FROM (VALUES(1, 5), (2, 9), (3, 6)) x(k,v)
), Grp AS (
SELECT [Key], [Value],
ROW_NUMBER() OVER (ORDER BY [Key]) - rn AS grp
FROM mytable AS m
LEFT JOIN Seq AS s ON m.Value = s.v
)
SELECT *
FROM Grp
Sortie :
Key Value grp
-----------------
1 5 0
2 9 0
3 6 0
6 5 3
7 9 3
8 6 3
grp
permet d'identifier précisément ces îles.
Il ne vous reste plus qu'à filtrer les groupes partiels :
;WITH Seq AS (
SELECT v, ROW_NUMBER() OVER(ORDER BY k) AS rn
FROM (VALUES(1, 5), (2, 9), (3, 6)) x(k,v)
), Grp AS (
SELECT [Key], [Value],
ROW_NUMBER() OVER (ORDER BY [Key]) - rn AS grp
FROM mytable AS m
LEFT JOIN Seq AS s ON m.Value = s.v
)
SELECT g1.[Key], g1.[Value]
FROM Grp AS g1
INNER JOIN (
SELECT grp
FROM Grp
GROUP BY grp
HAVING COUNT(*) = 3 ) AS g2
ON g1.grp = g2.grp
Remarque : La version initiale de cette réponse utilisait un INNER JOIN
à Seq
. Cela ne fonctionnera pas si le tableau contient des valeurs telles que 5, 42, 9, 6
, comme 42
sera filtré par le INNER JOIN
et cette séquence faussement identifiée comme valide. Le mérite revient à @HABO pour cette modification.