PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Gibt ein Array von Jahren als Jahresbereiche zurück

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

Produziert genau das gewünschte Ergebnis.

Wenn Sie mit einem Array von varchar (varchar[] , wandeln Sie es einfach in int[] um , bevor Sie fortfahren. Es scheint dafür eine vollkommen legale Form zu haben:

years::int[]

Ersetzen Sie den inneren Sub-Select durch den Namen Ihrer Quelltabelle im Produktivcode.

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

->

FROM  tbl

Da wir es mit einer natürlich aufsteigenden Zahl zu tun haben (das Jahr) können wir eine Abkürzung verwenden, um Gruppen aufeinanderfolgender Jahre zu bilden (die einen Bereich bilden). Ich subtrahiere das Jahr selbst von der Zeilennummer (sortiert nach Jahr). Für aufeinanderfolgende Jahre erhöhen sich sowohl die Zeilennummer als auch das Jahr um eins und erzeugen dasselbe grp Nummer. Andernfalls beginnt ein neuer Bereich.

Mehr zu Fensterfunktionen im Handbuch hier und hier .

Eine plpgsql-Funktion könnte in diesem Fall sogar noch schneller sein. Müsste man testen. Beispiele in diesen verwandten Antworten:
Bestellte Anzahl aufeinanderfolgender Wiederholungen / Duplikate
ROW_NUMBER() zeigt unerwartete Werte