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

Rozdělte hodnoty oddělené čárkami do cílové tabulky s pevným počtem sloupců

Ukládat hodnoty CSV do jednoho sloupce je obvykle špatný návrh. Pokud je to možné, použijte místo toho pole nebo správně normalizovaný návrh.

Zatímco zůstáváte ve své současné situaci ...

Pro známý malý maximální počet prvků

Jednoduché řešení bez triků nebo rekurze bude stačit:

SELECT id, 1 AS rnk
     , split_part(csv, ', ', 1) AS c1
     , split_part(csv, ', ', 2) AS c2
     , split_part(csv, ', ', 3) AS c3
     , split_part(csv, ', ', 4) AS c4
     , split_part(csv, ', ', 5) AS c5
FROM   tbl
WHERE  split_part(csv, ', ', 1) <> '' -- skip empty rows

UNION ALL
SELECT id, 2
     , split_part(csv, ', ', 6)
     , split_part(csv, ', ', 7)
     , split_part(csv, ', ', 8)
     , split_part(csv, ', ', 9)
     , split_part(csv, ', ', 10)
FROM   tbl
WHERE  split_part(csv, ', ', 6) <> '' -- skip empty rows

-- three more blocks to cover a maximum "around 20"

ORDER  BY id, rnk;

db<>fiddle zde

id je PK původní tabulky.
To samozřejmě předpokládá ', ' jako oddělovač.
Můžete se snadno přizpůsobit.

Související:

Pro neznámý počet prvků

Různé cesty. Jednosměrné použití regexp_replace() vyměnit každý pátý oddělovač před zrušením vnoření ...

-- for any number of elements
SELECT t.id, c.rnk
     , split_part(c.csv5, ', ', 1) AS c1
     , split_part(c.csv5, ', ', 2) AS c2
     , split_part(c.csv5, ', ', 3) AS c3
     , split_part(c.csv5, ', ', 4) AS c4
     , split_part(c.csv5, ', ', 5) AS c5
FROM   tbl t
     , unnest(string_to_array(regexp_replace(csv, '((?:.*?,){4}.*?),', '\1;', 'g'), '; ')) WITH ORDINALITY c(csv5, rnk)
ORDER  BY t.id, c.rnk;

db<>fiddle zde

To předpokládá, že zvolený oddělovač ; nikdy se objeví ve vašich řetězcích. (Stejně jako , se nikdy nemůže objevit.)

Vzor regulárního výrazu je klíč:'((?:.*?,){4}.*?),'

(?:) ... „nezachycující“ sada závorek
() ... „zachycení“ sady závorek
*? ... nežravý kvantifikátor
{4}? ... sekvence přesně 4 shod

Náhrada '\1;' obsahuje back-reference \1 .

'g' jako čtvrtý funkční parametr je vyžadován pro opakované nahrazení.

Další čtení:

Mezi další způsoby, jak to vyřešit, patří rekurzivní CTE nebo funkce vracející sadu ...

Vyplňovat zprava doleva

(Jak jste přidali v Jak vložit hodnoty začínající z pravé strany do sloupců? )
Jednoduše odpočítávejte čísla jako:

SELECT t.id, c.rnk
     , split_part(c.csv5, ', ', 5) AS c1
     , split_part(c.csv5, ', ', 4) AS c2
     , split_part(c.csv5, ', ', 3) AS c3
     , split_part(c.csv5, ', ', 2) AS c4
     , split_part(c.csv5, ', ', 1) AS c5
FROM ...

db<>fiddle zde



  1. Kdy použít MongoDB nebo jiné databázové systémy orientované na dokumenty?

  2. Výmluvná skupinaBy make SQLSTATE[42000] s platným SQL dotazem v Laravel 5.3

  3. Jak uniknout speciálním znakům v MySQL?

  4. Použití MySql mezi klauzulí s daty