2016-10-24 1 views
0

Wir haben eine Tabelle mit ID autoincrement Spalte mit Lücken. Jede Zeile hat auch ein created Datum.Finden Sie die Lücke in der ID-Spalte + wählen Sie die vorherige/nächste Datumspalte

Wir versuchen, für jede Lücken-ID (die fehlenden) das vorherige/nächste Datum herauszufinden, das in unserer Tabelle verfügbar ist.

Wir bauten bereits eine SQL, die die Lücken (Lösung von here) identifiziert, so habe ich sie in einer Tabelle gecached, aber von hier, wie Sie die prev/next created Datum zu finden, die die Lücke aus der ursprünglichen Tabelle abdeckt.

Eingang:

+----+------------+ 
| 84 | 1443728132 | 
| 91 | 1443728489 | 
| 93 | 1443729058 | 
| 94 | 1443729200 | 
+----+------------+ 

Ausgabe

+--------+------------+------------+ 
| gap_id | prev_dt | next_dt | 
+--------+------------+------------+ 
|  85 | 1443728132 | 1443728489 | 
|  86 | 1443728132 | 1443728489 | 
|  87 | 1443728132 | 1443728489 | 
|  88 | 1443728132 | 1443728489 | 
|  89 | 1443728132 | 1443728489 | 
|  90 | 1443728132 | 1443728489 | 
|  92 | 1443728489 | 1443729058 | 
+--------+------------+------------+ 

Ich landete mit Google BigQuery tun.

+2

Welche DBMS verwenden Sie? –

+0

spielt keine Rolle, wir können zu einer bevorzugten Lösung migrieren, da wir Systeme in vielen von ihnen haben, MySQL, Microsoft, BigQuery. – Pentium10

+1

Eine Lösung für die begrenzten Fähigkeiten von MySQL wird ** sehr ** anders aussehen als eine Lösung für ein DBMS, das [modernes SQL] unterstützt (http://modern-sql.com/slides) –

Antwort

1

Sollte auf den meisten anderen Datenbanken als MySQL arbeiten

select  * 

from  (select  lag (id) over (order by id) + 1         as gap_start 
         ,id - 1               as gap_end 
         ,lag (dt) over (order by id)          as dt_before_gap 
         ,dt                as dt_after_gap 
         ,case when lag (id) over (order by id) + 1 <> id then 'Y' end as is_gap 

      from  t 
      ) t 

where  is_gap = 'Y' 
; 
+0

Das läuft ziemlich gut. Vielen Dank. – Pentium10

+0

@ Pentium10, Sie sind willkommen –

2

ich die Ergebnisse in Bereiche Gruppierung würde empfehlen:

select min(id + 1) as first_missing_id, 
     (next_id - 1) as last_missing_id, 
     next_dte 
from (select t.*, 
      lead(id) over (order by id) as next_id, 
      lead(dte) over (order by id) as next_dte 
     from t 
    ) t 
where next_id <> id + 1 
group by next_id, next_dte; 

Erste individuelle ids heikel ist. Wenn Sie also 1, 1000000, 1000000000 haben, könnten Sie viele Zeilen generieren.

+0

Die Ergebnisse sind bereits von unteren Rand jeder Bereich gebaut. Keine Notwendigkeit zu aggregieren (next_id ist einzigartig) –

1

Für BigQuery Standard-SQL

WITH yourTable AS (
SELECT 84 AS id, 1443728132 AS dt UNION ALL 
SELECT 91 AS id, 1443728489 AS dt UNION ALL 
SELECT 93 AS id, 1443729058 AS dt UNION ALL 
SELECT 94 AS id, 1443729200 AS dt 
), 
nums AS (
    SELECT num 
    FROM UNNEST(GENERATE_ARRAY((SELECT MIN(id) FROM YourTable), (SELECT MAX(id) FROM YourTable))) AS num 
), 
gaps AS (
    SELECT 
    LAG (id) OVER (ORDER BY id) + 1 AS gap_start, 
    id - 1 AS gap_end, 
    LAG (dt) OVER (ORDER BY id) AS prev_dt, 
    dt AS next_dt, 
    CASE 
     WHEN LAG (id) OVER (ORDER BY id) + 1 <> id THEN 'Y' 
    END AS is_gap 
    FROM 
    yourTable 
) 
SELECT num as gap_id, prev_dt, next_dt 
FROM gaps JOIN nums 
ON num BETWEEN gap_start AND gap_end 
WHERE is_gap = 'Y' 
ORDER BY num 

Ausgang:

gap_id  prev_dt  next_dt 
85  1443728132 1443728489 
86  1443728132 1443728489 
87  1443728132 1443728489 
88  1443728132 1443728489 
89  1443728132 1443728489 
90  1443728132 1443728489 
92  1443728489 1443729058 
+0

Leider musste ich etwas anderes verwenden, da 'GENERATE_ARRAY' nur bis zu einer Million Einträge funktioniert, und ich hatte noch viel mehr Einträge zu erledigen. Ich hatte auch keine Ressourcen mehr wegen der 'Reihenfolge von', also musste ich es entfernen, und viel mehr statische Tabelle verwenden, um jede Querverbindung zu vermeiden. – Pentium10

+0

sicher: o) bitte beachten Sie - 'ORDER BY' ist nicht Teil der Logik überhaupt - nur entfernen Sie es - es ist in Beispiel nur für Präsentationszwecke! –

+0

wäre toll, wenn Sie Ihre endgültige Lösung hier teilen können –