2017-11-18 2 views
0

ich diese Daten in einer Tabelle haben:SQL spezielle Gruppe in Teradata

service | vat | ini_date | end_date 
    1  A 10/01/2017 31/01/2017 
    2  A 15/01/2017 28/02/2017 
    3  A 15/02/2017 31/03/2017 
    4  B 15/01/2017 31/03/2017 
    5  B 15/02/2017 31/03/2017 
    6  B 20/04/2017 31/05/2017 
    7  B 20/05/2017 31/05/2017 

Und ich habe durch die Mehrwertsteuer Services Gruppe wich Spiel in der Zeit haben.

Meine Ausgabe von dieser sollte:

group service | vat | ini_date | end_date 
    1 1  A 10/01/2017 31/01/2017 
    1 2  A 15/01/2017 28/02/2017 
    1 3  A 15/02/2017 31/03/2017 
    1 4  B 15/01/2017 31/03/2017 
    1 5  B 15/02/2017 31/03/2017 
    2 6  B 20/04/2017 31/05/2017 
    2 7  B 20/05/2017 31/05/2017 

ich keine Verfahren verwenden, kann ich mit einer gewissen analytischen Funktion bin versucht, aber es gibt eine Menge von Kasuistiken. Das Problem beginnt, wenn Sie mehr als drei Dienste haben, die zeitlich einzeln zusammenfallen.

Jede Idee ist willkommen. Danke :)

+2

zu testen (in der vorherigen Zeile zu spähen) Was die Logik ist "Gruppe 1" von "Gruppe 2" zu unterscheiden? – ceferrari

+0

Es ist eine Sequenz. Es muss neu gestartet werden, wenn die Leistung in der gleichen MwSt nicht rechtzeitig übereinstimmt. – Gentoozero

+0

Möchten Sie Lücken finden, in denen das vorherige 'end_date' größer ist als das aktuelle' ini_date', d. H. Alle überlappenden Perioden gruppieren? – dnoeth

Antwort

0

Es scheint, Sie für jeden "Block" der Zeit inkrementieren, so muss man eine "Lücke" in den Daten erkennen. Unten habe ich eine Postgres-Geige mit den Fensterfunktionen LEAD() verwendet, um festzustellen, ob es eine Lücke gibt, die dann unter Verwendung von DENSE_RANK() in der endgültigen Ausgabe angeordnet wird. In der zweiten cte "common_dates" wird eine korrelierte Unterabfrage verwendet, um ein Datum zu finden, an dem die nächste Lücke erkannt wurde. Diese Information wird dann verwendet, um das endgültige DENSE_RANK() zu bestellen. Es gibt möglicherweise eine effizientere Methode in Teradata, diese Unterabfrage auszuführen, aber ich kann das nicht ausprobieren).

NB: ich angenommen habe „Service“ für die Bestellung in der LEAD() Funktion und in der korrelierten Unterabfrage verwendet werden.

Anmerkungen: "Gruppe" ist nicht etwas, was ich als Spaltenname empfehlen würde, also habe ich stattdessen "group_num" verwendet und die Beispieldaten zum Testen der Abfrage erweitert.

Demo (PostgreSQL 9,6)

CREATE TABLE Table1 
    ("service" int, "vat" varchar(1), "ini_date" date, "end_date" date) 
; 

INSERT INTO Table1 
    ("service", "vat", "ini_date", "end_date") 
VALUES 
    (11, 'A', '2016-01-10 00:00:00', '2016-01-31 00:00:00'), 
    (21, 'A', '2016-01-15 00:00:00', '2016-02-28 00:00:00'), 
    (31, 'A', '2016-02-15 00:00:00', '2016-03-31 00:00:00'), 
    (41, 'B', '2016-01-15 00:00:00', '2016-03-31 00:00:00'), 
    (51, 'B', '2016-02-15 00:00:00', '2016-03-31 00:00:00'), 
    (61, 'B', '2016-04-20 00:00:00', '2016-05-31 00:00:00'), 
    (71, 'B', '2016-05-20 00:00:00', '2016-05-31 00:00:00'), 

    (91, 'A', '2017-01-10 00:00:00', '2017-01-31 00:00:00'), 
    (92, 'A', '2017-01-15 00:00:00', '2017-02-28 00:00:00'), 
    (93, 'A', '2017-02-15 00:00:00', '2017-03-31 00:00:00'), 
    (94, 'B', '2017-01-15 00:00:00', '2017-03-31 00:00:00'), 
    (95, 'B', '2017-02-15 00:00:00', '2017-03-31 00:00:00'), 
    (96, 'B', '2017-04-20 00:00:00', '2017-05-31 00:00:00'), 
    (97, 'B', '2017-05-20 00:00:00', '2017-05-31 00:00:00') 
; 

Abfrage 1:

with gapflag as (
     SELECT 
     * 
     , lag(end_date) over(order by service) - ini_date dfdts 
     , max(end_date) over() max_date 
     FROM Table1 
    ) 
, common_dates as (  
     select 
     * 
     , coalesce(
       (select ini_date 
       from gapflag t2 
       where t2.dfdts < 1 and t2.service > gapflag.service 
       order by service limit 1) 
       , 
       max_date 
      ) grp_date 
     from gapflag 
    ) 
select 
     dense_rank() over(order by grp_date) group_num 
    , service, vat, ini_date, end_date 
from common_dates 

Results:

| group_num | service | vat | ini_date | end_date | 
|-----------|---------|-----|------------|------------| 
|   1 |  11 | A | 2016-01-10 | 2016-01-31 | 
|   1 |  21 | A | 2016-01-15 | 2016-02-28 | 
|   1 |  31 | A | 2016-02-15 | 2016-03-31 | 
|   1 |  41 | B | 2016-01-15 | 2016-03-31 | 
|   1 |  51 | B | 2016-02-15 | 2016-03-31 | 
|   2 |  61 | B | 2016-04-20 | 2016-05-31 | 
|   2 |  71 | B | 2016-05-20 | 2016-05-31 | 
|   3 |  91 | A | 2017-01-10 | 2017-01-31 | 
|   3 |  92 | A | 2017-01-15 | 2017-02-28 | 
|   3 |  93 | A | 2017-02-15 | 2017-03-31 | 
|   3 |  94 | B | 2017-01-15 | 2017-03-31 | 
|   3 |  95 | B | 2017-02-15 | 2017-03-31 | 
|   4 |  96 | B | 2017-04-20 | 2017-05-31 | 
|   4 |  97 | B | 2017-05-20 | 2017-05-31 | 
0

Es sieht wollen Sie gruppieren servic Es überschneidet sich zeitlich mit Gruppen. Da sich die Services 1-5 (wie eine Kette) überlappen, werden sie zu "Group 1". Da sich der nächste Dienst (Dienst 6) nicht mit der vorherigen Gruppe überschneidet, geben Sie ihm die nächste ID - "Gruppe 2" und fahren fort. Ist das korrekt?

Wenn ja ... ein paar Funktionen, die Ihnen helfen können:

Fensterfunktionen
PERIODE Datentyp + bezogene Funktionen für Überlappung