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

Làm thế nào để chuyển đổi các giá trị được phân tách bằng dấu phẩy thành các hàng trong oracle?

Tôi đồng ý rằng đây là một thiết kế thực sự tồi. Hãy thử điều này nếu bạn không thể thay đổi thiết kế đó:

select distinct id, trim(regexp_substr(value,'[^,]+', 1, level) ) value, level
  from tbl1
   connect by regexp_substr(value, '[^,]+', 1, level) is not null
   order by id, level;

ĐẦU RA

id value level
1   AA  1
1   UT  2
1   BT  3
1   SK  4
1   SX  5
2   AA  1
2   UT  2
2   SX  3
3   UT  1
3   SK  2
3   SX  3
3   ZF  4

Tín dụng cho điều này

Để xóa các bản sao một cách thanh lịch và hiệu quả hơn (tín dụng cho @mathguy)

select id, trim(regexp_substr(value,'[^,]+', 1, level) ) value, level
  from tbl1
   connect by regexp_substr(value, '[^,]+', 1, level) is not null
      and PRIOR id =  id 
      and PRIOR SYS_GUID() is not null  
   order by id, level;

Nếu bạn muốn phương pháp tiếp cận "ANSIer", hãy sử dụng CTE:

with t (id,res,val,lev) as (
           select id, trim(regexp_substr(value,'[^,]+', 1, 1 )) res, value as val, 1 as lev
             from tbl1
            where regexp_substr(value, '[^,]+', 1, 1) is not null
            union all           
            select id, trim(regexp_substr(val,'[^,]+', 1, lev+1) ) res, val, lev+1 as lev
              from t
              where regexp_substr(val, '[^,]+', 1, lev+1) is not null
              )
select id, res,lev
  from t
order by id, lev;

ĐẦU RA

id  val lev
1   AA  1
1   UT  2
1   BT  3
1   SK  4
1   SX  5
2   AA  1
2   UT  2
2   SX  3
3   UT  1
3   SK  2
3   SX  3
3   ZF  4

Một cách tiếp cận đệ quy khác của MT0 nhưng không có regex:

WITH t ( id, value, start_pos, end_pos ) AS
  ( SELECT id, value, 1, INSTR( value, ',' ) FROM tbl1
  UNION ALL
  SELECT id,
    value,
    end_pos                    + 1,
    INSTR( value, ',', end_pos + 1 )
  FROM t
  WHERE end_pos > 0
  )
SELECT id,
  SUBSTR( value, start_pos, DECODE( end_pos, 0, LENGTH( value ) + 1, end_pos ) - start_pos ) AS value
FROM t
ORDER BY id,
  start_pos;

Tôi đã thử 3 cách tiếp cận với tập dữ liệu 30000 hàng và trả về 118104 hàng và nhận được kết quả trung bình sau:

  • Phương pháp đệ quy của tôi:5 giây
  • Phương pháp tiếp cận MT0:4 giây
  • Phương pháp tiếp cận Mathguy:16 giây
  • Phương pháp tiếp cận đệ quy MT0 không có regex:3,45 giây

@Mathguy cũng đã thử nghiệm với tập dữ liệu lớn hơn:

Trong tất cả các trường hợp, truy vấn đệ quy (tôi chỉ thử nghiệm truy vấn với quy định và hướng dẫn) hoạt động tốt hơn, theo hệ số từ 2 đến 5. Dưới đây là tổ hợp số chuỗi / mã thông báo trên mỗi chuỗi và các chế độ thực thi CTAS cho phân cấp so với đệ quy, phân cấp đầu tiên . Tất cả thời gian không an toàn

  • 30.000 x 4:5/1.
  • 30.000 x 10:15/3.
  • 30.000 x 25:56 / 37.
  • 5.000 x 50:33/14.
  • 5.000 x 100:160 / 81.
  • 10.000 x 200:1.924 / 772


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. chuyển mảng sang thủ tục oracle

  2. Làm thế nào để trả về tập kết quả từ thủ tục đã lưu trữ trong Oracle?

  3. Truy vấn con trong câu lệnh select hoạt động như thế nào trong oracle

  4. Không thể đăng nhập vào cơ sở dữ liệu bằng SYS với Oracle SQL Developer

  5. Khớp các giá trị cột trùng lặp của Oracle bằng cách sử dụng Soundex, Jaro Winkler và Chỉnh sửa Khoảng cách (UTL_MATCH)