PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Podziel wartości oddzielone przecinkami do tabeli docelowej ze stałą liczbą kolumn

Przechowywanie wartości CSV w jednej kolumnie jest zazwyczaj złym projektem. Jeśli to w ogóle możliwe, użyj zamiast tego tablicy lub odpowiednio znormalizowanego projektu.

Gdy utknąłeś w swojej obecnej sytuacji...

Dla znanej małej maksymalnej liczby elementów

Wystarczy proste rozwiązanie bez sztuczek i rekurencji:

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 tutaj

id będący PK oryginalnej tabeli.
Zakłada to oczywiście ',' jako separator.
Możesz łatwo dostosować.

Powiązane:

Dla nieznanej liczby elementów

Różne drogi. W jedną stronę użyj regexp_replace() wymienić co piąty separator przed rozgnieżdżeniem...

-- 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 tutaj

Zakłada się, że wybrany separator ; nigdy pojawia się w twoich strunach. (Podobnie jak , nigdy się nie pojawi.)

Wzorzec wyrażenia regularnego to klucz:'((?:.*?,){4}.*?),'

(?:) ... zestaw „nieprzechwytujących” nawiasów
() ... „przechwytywanie” zestawu nawiasów
*? ... kwantyfikator nie zachłanny
{4}? ... sekwencja dokładnie 4 dopasowań

Zastępczy '\1;' zawiera odniesienie wsteczne \1 .

'g' jako czwarty parametr funkcji jest wymagany do powtórnej wymiany.

Dalsza lektura:

Inne sposoby rozwiązania tego problemu obejmują rekurencyjne CTE lub funkcję zwracania zestawu ...

Wypełnij od prawej do lewej

(Tak jak dodałeś w Jak umieścić wartości zaczynające się od prawej strony w kolumnach? )
Po prostu odliczaj liczby, takie jak:

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 tutaj



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak ustawić domyślny schemat w Yii2

  2. postgres do MS Access

  3. Jak używać operatorów PostgreSQL JSON(B) zawierających znak zapytania? przez JDBC

  4. Formatowanie daty dla Postgresql

  5. PostgreSql :tablica Json do wierszy przy użyciu łączenia bocznego