Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Erhalten Sie die Anzahl der aufeinanderfolgenden Tage, die ein bestimmtes Kriterium erfüllen

Diese Abfrage ergibt die Anzahl für jede Zeile:

SELECT allocation, d, count(*) OVER (PARTITION BY allocation, part ORDER BY d) AS c
FROM (
  SELECT allocation, d,
         d - row_number() OVER (PARTITION BY allocation ORDER BY d) AS part
  FROM t
)
ORDER BY d;

Sie können dann danach filtern, um die Anzahl für eine bestimmte Zeile zu finden:

SELECT c
FROM (
  SELECT allocation, d, count(*) OVER (PARTITION BY allocation, part ORDER BY d) AS c
  FROM (
    SELECT allocation, d,
           d - row_number() OVER (PARTITION BY allocation ORDER BY d) AS part
    FROM t
  )
)
WHERE d = DATE '2015-01-05';

Erklärung:

Die abgeleitete Tabelle wird verwendet, um verschiedene "Partitionen" part zu berechnen für jedes Datum und jede Zuordnung:

  SELECT allocation, d,
         d - row_number() OVER (PARTITION BY allocation ORDER BY d) AS part
  FROM t

Das Ergebnis ist:

allocation  d           part
--------------------------------
Same        01.01.15    31.12.14
Good        02.01.15    01.01.15
Same        03.01.15    01.01.15
Same        04.01.15    01.01.15
Same        05.01.15    01.01.15
Good        06.01.15    04.01.15

Das konkrete Datum, das von part erzeugt wird ist irrelevant. Es ist nur ein Datum, das für jede "Gruppe" von Daten innerhalb einer Zuordnung gleich ist. Sie können dann die Anzahl der identischen Werte von (allocation, part) zählen mit dem count(*) over(...) Fensterfunktion:

SELECT allocation, d, count(*) OVER (PARTITION BY allocation, part ORDER BY d) AS c
FROM (...)
ORDER BY d;

um das gewünschte Ergebnis zu erzielen.

Daten

Ich habe die folgende Tabelle für das Beispiel verwendet:

CREATE TABLE t AS (
  SELECT DATE '2015-01-01' AS d, 'Same' AS allocation FROM dual UNION ALL
  SELECT DATE '2015-01-02' AS d, 'Good' AS allocation FROM dual UNION ALL
  SELECT DATE '2015-01-03' AS d, 'Same' AS allocation FROM dual UNION ALL
  SELECT DATE '2015-01-04' AS d, 'Same' AS allocation FROM dual UNION ALL  
  SELECT DATE '2015-01-05' AS d, 'Same' AS allocation FROM dual UNION ALL
  SELECT DATE '2015-01-06' AS d, 'Good' AS allocation FROM dual
);