sql >> Database teknologi >  >> RDS >> PostgreSQL

Returner matrix af år som årrækker

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
 

Producerer præcis det ønskede resultat.

Hvis du beskæftiger dig med en række varchar (varchar[] , bare cast den til int[] , før du fortsætter. Det ser ud til at være i fuldkommen lovlig form for det:

years::int[]
 

Erstat det indre undervalg med navnet på din kildetabel i produktiv kode.

FROM (VALUES (2::int, '{1999,2000,2010,2011,2012}'::int[]) ,(3, '{1990,1991,2007}') ) AS tbl(id, years)

->

FROM  tbl
 

Da vi har at gøre med et naturligt stigende tal (året) kan vi bruge en genvej til at danne grupper af på hinanden følgende år (danner et interval). Jeg trækker selve året fra rækkenummer (ordnet efter år). I på hinanden følgende år stiger både rækkenummer og år med én og producerer den samme grp nummer. Ellers starter en ny serie.

Mere om vinduefunktioner i manualen her og her .

En plpgsql-funktion kan være endnu hurtigere i dette tilfælde. Du skulle teste. Eksempler i disse relaterede svar:
Bestilt antal på hinanden følgende gentagelser/duplikater
ROW_NUMBER() viser uventede værdier



  1. MySQL - to afhængige vægtede gennemsnit i en enkelt forespørgsel

  2. Hvordan vælger man rækker, der har dagens tidsstempel?

  3. SQL-transponer fuld tabel

  4. sql-forespørgsel for at returnere forskelle mellem to tabeller