2012-11-02 18 views
6

là có điều như vậy trong oracle như chức năng listunagg? Ví dụ, nếu tôi có một dữ liệu như:chức năng listunagg?

------------------------------------------------------------ 
| user_id | degree_fi | degree_en  | degree_sv  | 
-------------------------------------------------------------- 
| 3601464 | 3700   | 1600   | 2200   | 
| 1020 | 100   | 0    | 0    | 
| 3600520 | 100,3200,400 | 1300, 800, 3000 | 1400, 600, 1500 | 
| 3600882 | 0   | 100   | 200   | 
-------------------------------------------------------------- 

và tôi muốn hiển thị dữ liệu như thế này:

----------------------------------------------- 
| user_id | degree_fi | degree_en | degree_sv | 
----------------------------------------------- 
| 3601464 | 3700  | 1600  | 2200  | 
| 1020 | 100  | 0  | 0  | 
| 3600520 | 100  | 1300  | 1400  | 
| 3600882 | 0  | 100  | 200  | 
| 3600520 | 3200  | 800  | 600  | 
| 3600520 | 400  | 3000  | 1500  | 
----------------------------------------------- 

Tôi cố gắng để tìm thấy một số chức năng như trái ngược với listagg nhưng không thể tìm thấy bất kì. Cảm ơn trước :-)

+0

không, không có chức năng gốc như vậy. chỉ cách giải quyết tùy chỉnh –

+1

bản sao có thể có của [cách chuyển đổi csv thành bảng trong oracle] (http://stackoverflow.com/questions/3142665/how-to-convert-csv-to-table-in-oracle) – APC

Trả lời

7

Như @be ở đây hiện đã có ghi chú trong nhận xét Oracle không cung cấp chức năng như vậy. Vì vậy, như một cách giải quyết nhanh chóng bạn có thể viết truy vấn tương tự:

with t1(user_id, degree_fi, degree_en, degree_sv) as 
(
    select 3601464, '3700', '1600', '2200' from dual union all 
    select 1020 , '100' , '0' , '0' from dual union all 
    select 3600520, '100,3200,400', '1300, 800, 3000', '1400, 600, 1500' from dual union all 
    select 3600882, '0', '100', '200' from dual 
), 
Occurence(ocr) as(
    select Level as ocr 
    from (select max(greatest(regexp_count(degree_fi, '[^,]+') 
          , regexp_count(degree_en, '[^,]+') 
          , regexp_count(degree_sv, '[^,]+') 
          ) 
        ) mx 
      from t1  
     ) 
    connect by level <= mx 
) 
select * 
    from (
select User_id 
    , regexp_substr(degree_fi, '[^,]+', 1, o.ocr) as degree_fi 
    , regexp_substr(degree_en, '[^,]+', 1, o.ocr) as degree_en 
    , regexp_substr(degree_sv, '[^,]+', 1, o.ocr) as degree_sv 
    from t1 t 
    cross join Occurence o 
) 
where degree_fi is not null 
    or degree_en is not null 
    or degree_sv is not null 

Kết quả:

User_Id Degree_Fi Degree_En Degree_Sv 
------------------------------------------------------------ 
3601464 3700  1600  2200 
1020  100  0   0 
3600520 100  1300  1400 
3600882 0   100  200 
3600520 3200  800  600 
3600520 400  3000  1500 
+1

Cảm ơn đây là những gì tôi cần :-) – Jaanna

0

Để unagg một danh sách xem xét những gì Tom đã nói tại của Oracle "Ask Tom" thấy http://www.oracle.com/technetwork/issue-archive/2007/07-mar/o27asktom-084983.html Mã 3 hoặc 4.

Tùy chọn ưa thích của tôi mà Tom không thảo luận tốt cho các chuỗi ngắn (< 34 ký tự). Tôi sử dụng hàm Oracle DBMS_UTILITY.comma_to_table. Ví dụ:

SET SERVEROUTPUT ON 
DECLARE 
/** test data **/ 
    L_LIST1 VARCHAR2(500) := '"A","B","C","Pierre - Andre","D","E","OFVampFVapos;CBryan","F","G","H","I","J"'; 
    l_list2 VARCHAR2(500); 
    l_tablen BINARY_INTEGER; 
    l_tab  DBMS_UTILITY.uncl_array; 
BEGIN 
    DBMS_OUTPUT.put_line('l_list1 : ' || l_list1); 

    DBMS_UTILITY.comma_to_table (
    list => l_list1, 
    tablen => l_tablen, 
    tab => l_tab); 

    FOR i IN 1 .. l_tablen LOOP 
    DBMS_OUTPUT.put_line(i || ' : ' || l_tab(i)); 
    END LOOP; 

    DBMS_UTILITY.table_to_comma (
    tab => l_tab, 
    tablen => l_tablen, 
    list => l_list2); 

    DBMS_OUTPUT.put_line('l_list2 : ' || l_list2); 
end;