PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

GROUP BY und aggregieren sequentielle numerische Werte

Das Identifizieren nicht aufeinanderfolgender Werte ist immer etwas knifflig und beinhaltet mehrere verschachtelte Unterabfragen (zumindest fällt mir keine bessere Lösung ein).

Der erste Schritt besteht darin, nicht aufeinanderfolgende Werte für das Jahr zu identifizieren:

Schritt 1) ​​Identifizieren Sie nicht aufeinanderfolgende Werte

select company, 
       profession,
       year,
       case 
          when row_number() over (partition by company, profession order by year) = 1 or 
               year - lag(year,1,year) over (partition by company, profession order by year) > 1 then 1
          else 0
       end as group_cnt
from qualification

Dies gibt das folgende Ergebnis zurück:

 company | profession | year | group_cnt
---------+------------+------+-----------
 Google  | Programmer | 2000 |         1
 Google  | Sales      | 2000 |         1
 Google  | Sales      | 2001 |         0
 Google  | Sales      | 2002 |         0
 Google  | Sales      | 2004 |         1
 Mozilla | Sales      | 2002 |         1

Jetzt können wir mit dem Wert group_cnt "Gruppen-IDs" für jede Gruppe erstellen, die aufeinanderfolgende Jahre hat:

Schritt 2) Gruppen-IDs definieren

select company,
   profession,
   year,
   sum(group_cnt) over (order by company, profession, year) as group_nr
from ( 
select company, 
       profession,
       year,
       case 
          when row_number() over (partition by company, profession order by year) = 1 or 
               year - lag(year,1,year) over (partition by company, profession order by year) > 1 then 1
          else 0
       end as group_cnt
from qualification
) t1

Dies gibt das folgende Ergebnis zurück:

 company | profession | year | group_nr
---------+------------+------+----------
 Google  | Programmer | 2000 |        1
 Google  | Sales      | 2000 |        2
 Google  | Sales      | 2001 |        2
 Google  | Sales      | 2002 |        2
 Google  | Sales      | 2004 |        3
 Mozilla | Sales      | 2002 |        4
(6 rows)

Wie Sie sehen können, hat jede „Gruppe“ ihre eigene Gruppennummer und diese können wir schließlich verwenden, um sie zu aggregieren, indem wir eine weitere abgeleitete Tabelle hinzufügen:

Schritt 3) Letzte Abfrage

select company,
       profession,
       array_agg(year) as years
from (
  select company,
       profession,
       year,
       sum(group_cnt) over (order by company, profession, year) as group_nr
  from ( 
    select company, 
           profession,
           year,
           case 
              when row_number() over (partition by company, profession order by year) = 1 or 
                   year - lag(year,1,year) over (partition by company, profession order by year) > 1 then 1
              else 0
           end as group_cnt
    from qualification
  ) t1
) t2
group by company, profession, group_nr
order by company, profession, group_nr

Dies gibt das folgende Ergebnis zurück:

 company | profession |      years
---------+------------+------------------
 Google  | Programmer | {2000}
 Google  | Sales      | {2000,2001,2002}
 Google  | Sales      | {2004}
 Mozilla | Sales      | {2002}
(4 rows)

Das ist genau das, was du wolltest, wenn ich mich nicht irre.