sql >> Databáze >  >> RDS >> PostgreSQL

Vraťte pole roků v rozsahu roků

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

Produkuje přesně požadovaný výsledek.

Pokud se zabýváte polem varchar (varchar[] , stačí jej přenést do int[] , než budete pokračovat. Zdá se, že je v naprosto legální formě:

years::int[]

Nahraďte vnitřní podvýběr názvem vaší zdrojové tabulky v produktivním kódu.

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

->

FROM  tbl

Protože máme co do činění s přirozeně stoupajícím číslem (rok) můžeme použít zkratku k vytvoření skupin po sobě jdoucích let (tvořících rozsah). Od čísla řádku odečítám samotný rok (seřazeno podle roku). V po sobě jdoucích letech se číslo řádku i rok zvýší o jednu a vytvoří stejný grp číslo. Jinak začíná nový rozsah.

Více o funkcích oken v příručce zde a zde .

Funkce plpgsql může být v tomto případě ještě rychlejší. Musel bys testovat. Příklady v těchto souvisejících odpovědích:
Seřazený počet po sobě jdoucích opakování / duplikátů
ROW_NUMBER() zobrazuje neočekávané hodnoty



  1. Oracle (11.2.0.1) :Jak identifikovat řádek, který je aktuálně aktualizován příkazem UPDATE

  2. Jak přidat datový soubor do databáze SQL Server (T-SQL)

  3. duplicitní prázdný řádek zadaný do mysql při nahrávání souboru

  4. Přidání indexu na velkou tabulku trvá věčnost