PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

GROUP BY i agregacja kolejnych wartości liczbowych

Identyfikacja niekolejnych wartości jest zawsze nieco trudna i obejmuje kilka zagnieżdżonych podzapytań (przynajmniej nie mogę wymyślić lepszego rozwiązania).

Pierwszym krokiem jest identyfikacja nienastępujących po sobie wartości dla roku:

Krok 1) Zidentyfikuj niekolejne wartości

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

Zwraca następujący wynik:

 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

Teraz z wartością group_cnt możemy utworzyć „identyfikatory grup” dla każdej grupy, która ma kolejne lata:

Krok 2) Zdefiniuj identyfikatory grup

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

Zwraca następujący wynik:

 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)

Jak widać, każda „grupa” ma swoją własną grupę_nr, którą możemy w końcu wykorzystać do agregacji poprzez dodanie kolejnej tabeli pochodnej:

Krok 3) Ostatnie zapytanie

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

Zwraca następujący wynik:

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

Dokładnie tego chciałeś, jeśli się nie mylę.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak wyodrębnić rok i miesiąc od daty w PostgreSQL bez użycia funkcji to_char()?

  2. Jak zmienić schemat wielu tabel PostgreSQL w jednej operacji?

  3. Automatyzacja Barmana z Puppet:it2ndq/barman (część pierwsza)

  4. Jak wybrać rekordy z ostatnich 24 godzin w PostgreSQL?

  5. Niezbędne monitorowanie PostgreSQL — część 3