Verwenden von Row_Number zum Ermitteln der Anzahl aufeinanderfolgender Zeilen

8

Ich habe diese Spalte mit Ints, die das Auftreten eines Signals darstellen, und ich versuche, eine Spalte hinzuzufügen, die die Anzahl aufeinanderfolgender Zeilen anzeigt

Wenn meine Daten so aussehen

724
727
728
733
735
737
743
747
749

Die resultierenden Daten mit einer aufeinanderfolgenden Zeilenanzahlspalte würden so aussehen

724 1
727 1
728 2
729 3
735 1
737 1
743 1
744 2
748 1

Ich habe es mit einer Schleifenfunktion gemacht, aber ich versuche es mit einem cte herauszufinden. Hier ist ein Beispiel meines letzten Versuchs

DECLARE @d TABLE ( signal INT )
INSERT  INTO @d
        SELECT  724
        UNION
        SELECT  727
        UNION
        SELECT  728
        UNION
        SELECT  729
        UNION
        SELECT  735
        UNION
        SELECT  737
        UNION
        SELECT  743
        UNION
        SELECT  744
        UNION
        SELECT  748 ;
WITH    a AS ( SELECT   signal,
                        ROW_NUMBER() OVER ( ORDER BY signal ) AS marker
               FROM     @d
             ) ,
        b AS ( SELECT   a1.signal,
                        CASE ( a1.signal - a2.signal )
                          WHEN 1 THEN 1
                          ELSE 0
                        END consecutiveMarker
               FROM     a a1
                        INNER JOIN a a2 ON a2.marker = a1.marker - 1
             )
    SELECT  *
    FROM    b

Erzeugt diese Ergebnisse

signal  consecutiveMarker
727 0
728 1
729 1
735 0
737 0
743 0
744 1
748 0

Das erste offensichtliche Problem ist das Fehlen des ersten Signals in einer Reihe. Ansonsten dachte ich, ich könnte dies dann mit einer row_number-Partitionierung auf dem aufeinanderfolgenden Marker an ein anderes cte übergeben. Das hat nicht funktioniert, weil es als eine Partition partitioniert wurde. Ich konnte keine Möglichkeit finden, der Partitionierungsmethode anzuzeigen, dass eine Serie von der nächsten getrennt ist

Jede Hilfe wird geschätzt.

OrangeYoda
quelle
1
Es scheint eine Nichtübereinstimmung zwischen den Quelldaten und den gewünschten Ergebnissen zu geben.
Martin Smith

Antworten:

16

Der allgemeine Name für diese Art von Abfrage lautet "Lücken und Inseln". Ein Ansatz unten. Wenn Sie Duplikate in den Quelldaten haben können, benötigen Sie möglicherweise dense_ranknichtrow_number

WITH DATA(C) AS
(
SELECT 724 UNION ALL
SELECT 727 UNION ALL
SELECT 728 UNION ALL
SELECT 729 UNION ALL
SELECT 735 UNION ALL
SELECT 737 UNION ALL
SELECT 743 UNION ALL
SELECT 744 UNION ALL
SELECT 747 UNION ALL
SELECT 749
), T1 AS
(
SELECT C,
       C - ROW_NUMBER() OVER (ORDER BY C) AS Grp
FROM DATA)
SELECT C,
       ROW_NUMBER() OVER (PARTITION BY Grp ORDER BY C) AS Consecutive
FROM T1

Kehrt zurück

C           Consecutive
----------- --------------------
724         1
727         1
728         2
729         3
735         1
737         1
743         1
744         2
747         1
749         1
Martin Smith
quelle
1

In SQL 2012 können Sie dies auch mit der LAG und den Fensterfunktionen tun, z

DECLARE @d TABLE ( signal INT PRIMARY KEY) 

INSERT INTO @d 
VALUES
    ( 724 ),
    ( 727 ),
    ( 728 ),
    ( 729 ),
    ( 735 ),
    ( 737 ),
    ( 743 ),
    ( 744 ),
    ( 748 )

SELECT signal
    , 1 + ( SUM( is_group ) OVER ( ORDER BY signal ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING ) * is_group )
FROM
    (
    SELECT *
        , CASE WHEN LAG(signal) OVER( ORDER BY signal ) = signal - 1 THEN 1 ELSE 0 END is_group
    FROM @d
    ) x
wBob
quelle
-1

Wie bei solchen Problemen üblich, ist dies in Java, C ++ oder C # sehr einfach zu bewerkstelligen.

Wenn Sie dies wirklich in der Datenbank tun müssen, können Sie ein RDBMS mit schnellen Cursorn wie Oracle verwenden, einen einfachen Cursor schreiben und eine schnelle Leistung genießen, ohne etwas Komplexes schreiben zu müssen.

Wenn Sie dies in T-SQL tun müssen und das Datenbankdesign nicht ändern können, hat Itzik Ben-Gan in "MVP Deep Dives Vol. 1" mehrere Lösungen und in seinem neuen Buch über Fensterfunktionen einige neue Lösungen mit OLAP-Funktionen geschrieben in SQL 2012.

Alternativ können Sie Ihrer Tabelle eine weitere aufeinanderfolgende Spalte hinzufügen und vorberechnete Werte darin speichern. Wir können Einschränkungen verwenden, um sicherzustellen, dass vorberechnete Daten immer gültig sind. Wenn jemand interessiert ist, kann ich erklären, wie.

AK
quelle