2011-10-11 34 views
22

tôi đã bàn 10g Oracle sau gọi _kv:Xoay vòng hàng vào cột động trong Oracle

select * from _kv 

ID  K  V 
----  ----- ----- 
    1  name Bob 
    1  age  30 
    1  gender male 
    2  name Susan 
    2  status married 

Tôi muốn quay chìa khóa của tôi vào cột sử dụng SQL đơn giản (không PL/SQL) để kết quả bảng sẽ giống như thế này:

ID  NAME AGE GENDER STATUS 
----  ----- ----- ------ -------- 
    1  Bob  30  male 
    2  Susan     married 
  • truy vấn nên có nhiều cột như độc đáo K s tồn tại trong bảng (không có nhiều)
  • Không có cách nào để biết những cột nào có thể tồn tại trước khi chạy truy vấn.
  • Tôi đang cố gắng tránh chạy truy vấn ban đầu để lập trình truy vấn cuối cùng theo chương trình.
  • Các ô trống có thể là rỗng hoặc các chuỗi rỗng, không thực sự quan trọng.
  • Tôi đang sử dụng Oracle 10g, nhưng giải pháp 11g cũng sẽ ổn.

Có rất nhiều ví dụ khi bạn biết những cột được xoay vòng của bạn có thể được gọi, nhưng tôi không thể tìm thấy giải pháp xoay vòng chung cho Oracle.

Cảm ơn!

+5

thân mến Thiên Chúa, là một ... meta DB ?? –

+2

Bạn nên đọc phần này: http://stackoverflow.com/questions/7340422/best-way-to-query-a-data-dictionary-in-sql/7340554#7340554 –

+0

Tôi luôn thấy hài hước khi đọc về ' giá trị thuộc tính thực thể 'bảng: http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:2314483800346542969 – Harrison

Trả lời

28

Oracle 11g cung cấp hoạt động PIVOT thực hiện những gì bạn muốn.

Oracle 11g giải pháp

select * from 
(select id, k, v from _kv) 
pivot(max(v) for k in ('name', 'age', 'gender', 'status') 

(Lưu ý: Tôi không có một bản sao của 11g để kiểm tra điều này trên vì vậy tôi đã không xác minh chức năng của nó)

tôi đắc giải pháp này từ : http://orafaq.com/wiki/PIVOT

EDIT - tùy chọn trục xml (cũng Oracle 11g)
Dường như cũng có tùy chọn pivot xml khi bạn không biết tất cả các tiêu đề cột có thể có mà bạn có thể cần. (Xem XML phần TYPE gần dưới cùng của trang tọa lạc tại http://www.oracle.com/technetwork/articles/sql/11g-pivot-097235.html)

select * from 
(select id, k, v from _kv) 
pivot xml (max(v) 
for k in (any)) 

(Lưu ý: Như trước đây tôi không có một bản sao của 11g để kiểm tra điều này trên vì vậy tôi đã không xác minh chức năng của nó)

Edit2: Changed v trong pivotpivot xml báo cáo để max(v) vì nó là vụ phải được tổng hợp như đã đề cập trong một trong các ý kiến. Tôi cũng đã thêm mệnh đề in không phải là tùy chọn cho pivot. Tất nhiên, phải xác định các giá trị trong mệnh đề in đánh bại mục tiêu của việc có một truy vấn pivot/crosstab hoàn toàn động như mong muốn của áp phích câu hỏi này.

+0

phần 'pivot (v cho k)' không hoạt động trong 11g, 'for' cần' in' và tôi không biết phải nhập gì vào mệnh đề 'in' – ojosilva

+1

@dave - chỉ hoạt động PIVOT làm việc với một tập hợp các cột cố định. Truy vấn của bạn không thể đột ngột trả về nhiều cột hơn vì một hàng bổ sung được thêm vào bảng. –

+0

@JustinCave, @ojosilva Tôi nghĩ rằng mệnh đề 'in' có thể là tùy chọn nếu bạn muốn giới hạn các cột thành các giá trị cụ thể và có thể bị bỏ sót nếu tất cả các giá trị đều được muốn. Có vẻ như có một tùy chọn 'pivot xml' liên quan đến điều này (xem câu trả lời được cập nhật). – dave

5

Xảy ra một nhiệm vụ trên trục xoay.Dưới đây làm việc cho tôi là thử nghiệm chỉ là bây giờ trên 11g:

select * from 
(
    select ID, COUNTRY_NAME, TOTAL_COUNT from ONE_TABLE 
) 
pivot(
    SUM(TOTAL_COUNT) for COUNTRY_NAME in (
    'Canada', 'USA', 'Mexico' 
) 
); 
6

Để đối phó với những tình huống mà có một khả năng của nhiều giá trị (v trong ví dụ của bạn), tôi sử dụng PIVOTLISTAGG:

SELECT * FROM 
(
    SELECT id, k, v 
    FROM _kv 
) 
PIVOT 
(
    LISTAGG(v ,',') 
    WITHIN GROUP (ORDER BY k) 
    FOR k IN ('name', 'age','gender','status') 
) 
ORDER BY id; 

Vì bạn muốn giá trị động, hãy sử dụng SQL động và chuyển các giá trị được xác định bằng cách chạy một lựa chọn trên dữ liệu bảng trước khi gọi báo cáo pivot.

0

Trước hết, trục động sử dụng pivot xml một lần nữa cần phải được phân tích cú pháp. Chúng tôi có một cách khác để làm điều này bằng cách lưu trữ các tên cột trong một biến và chuyển chúng trong sql động như dưới đây.

Hãy xem xét chúng tôi có một bảng như dưới đây.

enter image description here

Nếu chúng ta cần để hiển thị các giá trị trong cột YR như tên cột và các giá trị trong các cột từ QTY, sau đó chúng ta có thể sử dụng mã dưới đây.

declare 
    sqlqry clob; 
    cols clob; 
begin 
    select listagg('''' || YR || ''' as "' || YR || '"', ',') within group (order by YR) 
    into cols 
    from (select distinct YR from EMPLOYEE); 


    sqlqry := 
    '  
    select * from 
    (
     select * 
     from EMPLOYEE 
) 
    pivot 
    (
    MIN(QTY) for YR in (' || cols || ') 
)'; 

    execute immediate sqlqry; 
end; 
/

KẾT QUẢ

enter image description here

Các vấn đề liên quan