L'identification de valeurs non consécutives est toujours un peu délicate et implique plusieurs sous-requêtes imbriquées (du moins, je ne peux pas trouver de meilleure solution).
La première étape consiste à identifier les valeurs non consécutives pour l'année :
Étape 1) Identifiez les valeurs non consécutives
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
Cela renvoie le résultat suivant :
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
Maintenant, avec la valeur group_cnt, nous pouvons créer des "identifiants de groupe" pour chaque groupe qui a des années consécutives :
Étape 2) Définir les identifiants de groupe
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
Cela renvoie le résultat suivant :
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)
Comme vous pouvez le voir, chaque "groupe" a son propre group_nr et nous pouvons enfin l'utiliser pour agréger en ajoutant encore une autre table dérivée :
Étape 3) Requête finale
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
Cela renvoie le résultat suivant :
company | profession | years ---------+------------+------------------ Google | Programmer | {2000} Google | Sales | {2000,2001,2002} Google | Sales | {2004} Mozilla | Sales | {2002} (4 rows)
C'est exactement ce que vous vouliez, si je ne me trompe pas.