Bạn đã gần xong - thứ bạn muốn là sự kết hợp của UNPIVOT
và PIVOT
:
with T AS (
select 1 as element, 1.1 as reading1, 1.2 as reading2, 1.3 as reading3 from dual union all
select 2 as element, 2.1 as reading1, 2.2 as reading2, 2.3 as reading3 from dual union all
select 3 as element, 3.1 as reading1, 3.2 as reading2, 3.3 as reading3 from dual
)
select * from (
select * from t
unpivot (reading_value
for reading_name in ("READING1", "READING2", "READING3")
)
pivot(max(reading_value) for element in (1,2,3)
)
)
order by reading_name
Truy vấn này
- chuyển đổi các cột đọc1, đọc2, đọc3 thành các hàng riêng biệt (tên chuyển thành read_name , giá trị thành read_value ); điều này cung cấp cho chúng tôi một hàng cho mỗi (phần tử, read_name)
- chuyển đổi hàng 1, 2 *, 3 (các giá trị cho phần tử ) thành các cột '1', '2', '3'; điều này cung cấp cho chúng tôi một hàng cho mỗi read_name
CẬP NHẬT
Nếu danh sách các phần tử không được biết cho đến thời gian chạy (ví dụ:vì người dùng có tùy chọn chọn chúng), bạn cần một cách tiếp cận năng động hơn. Đây là một giải pháp tạo động một câu lệnh SQL cho danh sách các phần tử đã cho và sử dụng sys_refcursor
cho tập hợp kết quả.
-- setup table
create table T AS
select 1 as element, 1.1 as reading1, 1.2 as reading2, 1.3 as reading3 from dual union all
select 2 as element, 2.1 as reading1, 2.2 as reading2, 2.3 as reading3 from dual union all
select 3 as element, 3.1 as reading1, 3.2 as reading2, 3.3 as reading3 from dual ;
/
declare
l_Elements dbms_sql.Number_Table;
function pivot_it(p_Elements in dbms_sql.Number_Table)
return sys_refcursor is
l_SQL CLOB := empty_clob();
l_Result sys_refcursor;
begin
l_SQL := '
select * from (
select * from t
unpivot (reading_value
for reading_name in ("READING1", "READING2", "READING3")
)
pivot(max(reading_value) for element in (';
for i in 1 .. p_Elements.count
loop
l_SQL := l_SQL || to_char(p_Elements(i)) || ',';
end loop;
-- remove trailing ','
l_SQL := regexp_replace(l_SQL, ',$');
l_SQL := l_SQL || ')
)
)';
dbms_output.put_line(l_SQL);
open l_Result for l_SQL;
return l_Result;
end;
begin
l_Elements(1) := 1;
l_Elements(2) := 2;
-- uncomment this line to get all 3 elements
-- l_Elements(3) := 3;
-- return the cursor into a bind variable (to be used in the host environment)
:p_Cursor := pivot_it(l_Elements);
end;
Cách bạn sử dụng con trỏ được trả về từ hàm này tùy thuộc vào môi trường bạn đang sử dụng - trong SQL / Plus, bạn chỉ có thể in nó và các ràng buộc Oracle của hầu hết các ngôn ngữ lập trình đều hỗ trợ nó ngay lập tức.
CAVEAT: Mặc dù mã này hoạt động cho dữ liệu được cung cấp, nhưng nó thậm chí còn thiếu tính năng kiểm tra lỗi cơ bản. Điều này đặc biệt quan trọng vì SQL động luôn là mục tiêu có thể xảy ra cho các cuộc tấn công SQL injection.