PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Renvoie un tableau d'années sous forme de plages d'années

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