有一些静态透视方法,例如使用PIVOT 子句和Conditional Aggregation,所有生成的透视列都应该明确指定,而没有 通过使用仅SQL的直接动态方法。
我认为在存储函数中使用 SYS_REFCURSOR 非常适合您的情况:
CREATE OR REPLACE FUNCTION
Get_Table1_RS(
i_number table1."number"%TYPE
) RETURN SYS_REFCURSOR IS
v_recordset SYS_REFCURSOR;
v_sql VARCHAR2(32767);
v_str VARCHAR2(32767);
BEGIN
SELECT LISTAGG( ''''||time||''' AS "'||LOWER(c.column_name)||t.rn||'"' , ',' )
WITHIN GROUP ( ORDER BY time )
INTO v_str
FROM ( SELECT t1.*, ROW_NUMBER() OVER (ORDER BY time) AS rn
FROM table1 t1
WHERE "number" = '001' ) t
LEFT JOIN user_tab_cols c
ON c.table_name = 'TABLE1'
AND c.column_name like 'TIME%';
v_sql :=
'SELECT *
FROM table1
PIVOT
(
MAX(time) FOR time IN ( '|| v_str ||' )
)
WHERE "number" = :nr';
OPEN v_recordset FOR v_sql USING i_number;
RETURN v_recordset;
END;
/
为了获得动态生成的结果集(例如Dynamic Pivot)。
然后运行以下代码:
VAR rc REFCURSOR
EXEC :rc := Get_Table1_RS('001');
PRINT rc
从 SQL Developer 的命令行查看结果集。
如果您仍然只想使用 SQL 查询,那么更喜欢使用:
pivot子句的情况:
SELECT *
FROM table1
PIVOT
(
MAX(time) FOR time IN ( '12:30' AS "time1",'14:31' AS "time2",
'17:20' AS "time3",'19:01' AS "time4" )
)
WHERE "number" = '001';
number date time1 time2 time3 time4
------ ----------- ----- ----- ----- -----
001 19.09.2020 12:30 14:31 17:20 19:01
条件聚合的情况:
SELECT "number", "date",
MAX(CASE WHEN rn = 1 THEN time END) AS "time1",
MAX(CASE WHEN rn = 2 THEN time END) AS "time2",
MAX(CASE WHEN rn = 3 THEN time END) AS "time3",
MAX(CASE WHEN rn = 4 THEN time END) AS "time4"
FROM ( SELECT ROW_NUMBER() OVER (ORDER BY time) AS rn,
t1.*
FROM table1 t1
WHERE "number" = '001' ) t
GROUP BY "number", "date"
number date time1 time2 time3 time4
------ ----------- ----- ----- ----- -----
001 19.09.2020 12:30 14:31 17:20 19:01