sql >> Database teknologi >  >> RDS >> Sqlserver

Hvordan identificerer du optagelsesmønstersekvenser i poster ved hjælp af TSQL?

Du kan bruge følgende forespørgsel pakket ind i en CTE for at tildele sekvensnumre til værdierne i din sekvens:

;WITH Seq AS ( SELECT v, ROW_NUMBER() OVER(ORDER BY k) AS rn FROM (VALUES(1, 5), (2, 9), (3, 6)) x(k,v) )

Output:

v   rn
-------
5   1
9   2
6   3
 

Ved at bruge ovenstående CTE du kan identificere øer, dvs. udsnit af sekventielle rækker, der indeholder hele sekvensen:

;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

Output:

    Key Value   grp
   -----------------
    1   5       0
    2   9       0
    3   6       0
    6   5       3
    7   9       3
    8   6       3
 

grp felt hjælper dig med at identificere præcis disse øer.

Alt du skal gøre nu er blot at filtrere delvise grupper fra:

;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

Demo her

Bemærk: Den oprindelige version af dette svar brugte en INNER JOIN til Seq . Dette virker ikke, hvis tabellen indeholder værdier som 5, 42, 9, 6 , som 42 vil blive filtreret fra af INNER JOIN og denne sekvens fejlagtigt identificeret som en gyldig. Kredit går til @HABO for denne redigering.



  1. Del strengen i rækken

  2. PHP/mysql:hvordan viser jeg poster sorteret efter tid og grupperet efter dato?

  3. Arbejd med BLOB-objekt i Oracle

  4. vælg sætning i postgres-funktionen kaldet inde i en trigger