PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Pisahkan nilai yang dipisahkan koma ke dalam tabel target dengan jumlah kolom tetap

Biasanya desain yang buruk untuk menyimpan nilai CSV dalam satu kolom. Jika memungkinkan, gunakan array atau desain yang dinormalisasi dengan benar.

Sementara terjebak dengan situasi Anda saat ini ...

Untuk jumlah maksimum elemen kecil yang diketahui

Solusi sederhana tanpa tipu daya atau rekursi akan berhasil:

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 di sini

id menjadi PK dari tabel asli.
Ini mengasumsikan ', ' sebagai pemisah, tentu saja.
Anda dapat beradaptasi dengan mudah.

Terkait:

Untuk jumlah elemen yang tidak diketahui

Berbagai cara. Sekali jalan gunakan regexp_replace() untuk mengganti setiap pemisah kelima sebelum membuka sarang ...

-- 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 di sini

Ini mengasumsikan bahwa pemisah yang dipilih ; tidak pernah muncul di string Anda. (Sama seperti , tidak akan pernah muncul.)

Pola ekspresi reguler adalah kuncinya:'((?:.*?,){4}.*?),'

(?:) ... kumpulan tanda kurung “non-capturing”
() ... kumpulan tanda kurung “menangkap”
*? ... pengukur tidak serakah
{4}? ... urutan tepat 4 kecocokan

Pengganti '\1;' berisi referensi balik \1 .

'g' karena parameter fungsi keempat diperlukan untuk penggantian berulang.

Bacaan lebih lanjut:

Cara lain untuk menyelesaikan ini termasuk CTE rekursif atau fungsi set-return ...

Isi dari kanan ke kiri

(Seperti yang Anda tambahkan di Bagaimana cara memasukkan nilai mulai dari sisi kanan ke dalam kolom? )
Cukup hitung mundur angka seperti:

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 di sini



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Gabung Kiri Lateral dan agregat array

  2. PostgreSQL JDBC getGeneratedKeys mengembalikan semua kolom

  3. Banyak ke Banyak SQL Query untuk memilih semua Gambar Ditandai dengan kata-kata tertentu

  4. Bergabunglah dengan Kolom Alias ​​​​SQL

  5. Apa yang setara dengan REF CURSOR Oracle di Postgresql saat menggunakan JDBC?