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

Restituisce la matrice di anni come intervalli di anni

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

Produce esattamente il risultato desiderato.

Se hai a che fare con un array di varchar (varchar[] , lancialo su int[] , prima di procedere. Sembra essere in forma perfettamente legale per questo:

years::int[]

Sostituisci la sottoselezione interna con il nome della tua tabella di origine nel codice produttivo.

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

->

FROM  tbl

Poiché abbiamo a che fare con un numero naturalmente crescente (l'anno) possiamo usare una scorciatoia per formare gruppi di anni consecutivi (formando un intervallo). Sottrai l'anno stesso dal numero di riga (ordinato per anno). Per anni consecutivi, sia il numero di riga che l'anno aumentano di uno e producono lo stesso grp numero. Altrimenti, inizia una nuova gamma.

Ulteriori informazioni sulle funzioni della finestra nel manuale qui e qui .

Una funzione plpgsql potrebbe essere ancora più veloce in questo caso. Dovresti fare un test. Esempi in queste risposte correlate:
Conteggio ordinato di ripetizioni/duplicati consecutivi
ROW_NUMBER() mostra valori imprevisti