sql >> Database >  >> RDS >> PostgreSQL

Retourneer reeks jaren als jaarbereiken

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

Produceert precies het gewenste resultaat.

Als je te maken hebt met een array van varchar (varchar[] , cast het gewoon naar int[] , voordat u verder gaat. Het lijkt daarvoor in volkomen legale vorm te zijn:

years::int[]

Vervang de innerlijke subselectie door de naam van uw brontabel in productieve code.

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

->

FROM  tbl

Aangezien we te maken hebben met een natuurlijk oplopend getal (het jaar) kunnen we een snelkoppeling gebruiken om groepen van opeenvolgende jaren te vormen (een bereik vormen). Ik trek het jaar zelf af van het rijnummer (geordend op jaar). Voor opeenvolgende jaren worden zowel het rijnummer als het jaar met één verhoogd en produceren dezelfde grp nummer. Anders begint er een nieuw assortiment.

Meer over vensterfuncties in de handleiding hier en hier .

Een plpgsql-functie is in dit geval misschien nog sneller. Je zou moeten testen. Voorbeelden in deze gerelateerde antwoorden:
Geordende telling van opeenvolgende herhalingen / duplicaten
ROW_NUMBER() toont onverwachte waarden



  1. SQLite-subquery

  2. SQLAlchemy geen wachtwoord opgegeven fout

  3. Fout in Oracle PL/SQL-procedure

  4. Geen MySQL-records keren terug wanneer een bepaalde limiet wordt overschreden?