PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

GROUP BY и агрегирани последователни числови стойности

Идентифицирането на непоследователни стойности винаги е малко сложно и включва няколко вложени подзаявки (поне аз не мога да намеря по-добро решение).

Първата стъпка е да се идентифицират непоследователни стойности за годината:

Стъпка 1) Идентифицирайте непоследователни стойности

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

Това връща следния резултат:

 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

Сега със стойността group_cnt можем да създадем "идентификатори на група" за всяка група, която има последователни години:

Стъпка 2) Дефинирайте групови идентификатори

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

Това връща следния резултат:

 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)

Както можете да видите, всяка „група“ има свой group_nr и това накрая можем да използваме за обобщаване, като добавим още една извлечена таблица:

Стъпка 3) Окончателна заявка

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

Това връща следния резултат:

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

Това е точно това, което искахте, ако не се лъжа.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Пазете PostgreSQL понякога да избира лош план за заявка

  2. ClassNotFoundException с PostgreSQL и JDBC

  3. Как да картографирате PostgreSQL enum с JPA и Hibernate

  4. Как да включите изключените редове в ВРЪЩАНЕ от INSERT ... ПРИ КОНФЛИКТ

  5. psql:ФАТАЛНО:Удостоверяването на партньора е неуспешно за потребителски dev