SELECT id, string_agg(year_range, ', ') AS year_ranges
FROM (
SELECT id, CASE WHEN count(*) > 1
THEN min(year)::text || '-' || max(year)::text
ELSE min(year)::text
END AS year_range
FROM (
SELECT *, row_number() OVER (ORDER BY id, year) - year AS grp
FROM (
SELECT id, unnest(years) AS year
FROM (VALUES (2::int, '{1999,2000,2010,2011,2012}'::int[])
,(3, '{1990,1991,2007}')
) AS tbl(id, years)
) sub1
) sub2
GROUP BY id, grp
ORDER BY id, min(year)
) sub3
GROUP BY id
ORDER BY id
Produit exactement le résultat souhaité.
Si vous traitez avec un tableau de varchar (varchar[]
, il suffit de le caster en int[]
, avant de continuer. Il semble être sous une forme parfaitement légale pour cela :
years::int[]
Remplacez la sous-sélection interne par le nom de votre table source dans le code productif.
FROM (VALUES (2::int, '{1999,2000,2010,2011,2012}'::int[])
,(3, '{1990,1991,2007}')
) AS tbl(id, years)
->
FROM tbl
Puisque nous avons affaire à un nombre naturellement croissant (l'année) nous pouvons utiliser un raccourci pour former des groupes d'années consécutives (formant une plage). Je soustrais l'année elle-même du numéro de ligne (classé par année). Pour les années consécutives, le numéro de ligne et l'année sont incrémentés d'une unité et produisent le même grp
Numéro. Sinon, une nouvelle plage commence.
En savoir plus sur les fonctions de fenêtre dans le manuel ici et ici .
Une fonction plpgsql pourrait être encore plus rapide dans ce cas. Tu devrais tester. Exemples dans ces réponses associées :
Nombre ordonné de répétitions / doublons consécutifs
ROW_NUMBER() affiche des valeurs inattendues