PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Chia các giá trị được phân tách bằng dấu phẩy thành bảng mục tiêu với số lượng cột cố định

Việc lưu trữ các giá trị CSV trong một cột thường là một thiết kế tồi. Nếu có thể, hãy sử dụng một mảng hoặc một thiết kế chuẩn hóa thích hợp để thay thế.

Trong khi mắc kẹt với tình hình hiện tại của bạn ...

Đối với số phần tử tối đa nhỏ đã biết

Một giải pháp đơn giản không cần thủ thuật hoặc đệ quy sẽ thực hiện được:

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 tại đây

id là PK của bảng gốc.
Điều này giả định rõ ràng là ',' là dấu phân cách.
Bạn có thể điều chỉnh dễ dàng.

Có liên quan:

Đối với số phần tử không xác định

Nhiều cách khác nhau. Một cách sử dụng regexp_replace() để thay thế mọi dấu phân cách thứ năm trước khi bỏ ghi chú ...

-- 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 tại đây

Điều này giả định rằng dấu phân tách đã chọn ; không bao giờ xuất hiện trong chuỗi của bạn. (Cũng giống như , không bao giờ có thể xuất hiện.)

Mẫu biểu thức chính quy là khóa:'((?:.*?,){4}.*?),'

(?:) ... tập hợp dấu ngoặc đơn “không ghi lại”
() ... “thu thập” tập hợp các dấu ngoặc đơn
*? ... công cụ định lượng không tham lam
{4}? ... chuỗi đúng 4 trận

Thay thế '\1;' chứa tham chiếu ngược \1 .

'g' vì tham số chức năng thứ tư là bắt buộc để thay thế nhiều lần.

Đọc thêm:

Các cách khác để giải quyết vấn đề này bao gồm CTE đệ quy hoặc hàm trả về tập hợp ...

Điền từ phải sang trái

(Giống như bạn đã thêm trong Làm cách nào để đặt các giá trị bắt đầu từ phía bên phải vào cột? )
Đơn giản chỉ cần đếm ngược các số như:

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 tại đây



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Lỗi PostGres Khi Sử dụng Khác biệt:Postgres LỖI:không thể xác định một toán tử đặt hàng cho bản ghi loại

  2. Chèn hàng loạt từ csv trong postgres bằng golang mà không sử dụng vòng lặp for

  3. lỗi postgreSQL initdb:không tìm thấy lệnh

  4. PostgreSQL - Gán giá trị số nguyên cho chuỗi trong câu lệnh trường hợp

  5. node-postgres gặp lỗi kết nối ECONNREFUSED