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í:
- PostgreSQL a regexp_split_to_array + /a>
- Použít ` trim()` a `regexp_replace()` v textovém poli
- PostgreSQL unnest() s číslem prvku
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