Sql oracle中是否有任何语句可以将行值转换为同一行但不同的列?
我希望有人能给我一个问题的答案 我得到了一个表(即Sql oracle中是否有任何语句可以将行值转换为同一行但不同的列?,sql,oracle,plsql,oracle11g,pivot,Sql,Oracle,Plsql,Oracle11g,Pivot,我希望有人能给我一个问题的答案 我得到了一个表(即表1),它看起来像这样,我希望它像我在图片中显示的那样: 表1 "number" "date" time ------- ---------- ----- 001 19.09.2020 12:30 001 19.09.2020 14:31 002 19.09.2020 11:20 001 19.09.2020
表1
),它看起来像这样,我希望它像我在图片中显示的那样:
表1
"number" "date" time
------- ---------- -----
001 19.09.2020 12:30
001 19.09.2020 14:31
002 19.09.2020 11:20
001 19.09.2020 17:20
002 19.09.2020 14:00
001 19.09.2020 19:01
预期结果(对于“数字”=“001”):
有一些静态数据透视方法,如使用
PIVOT
子句和条件聚合
,其中所有生成的数据透视列都应显式指定,而有无直接动态方法,通过使用仅SQL
我认为在存储函数中使用SYS\u 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;
/
为了获得动态生成的结果集(例如,动态轴)
然后运行以下代码:
VAR rc REFCURSOR
EXEC :rc := Get_Table1_RS('001');
PRINT rc
从SQL Developer的命令行,以查看结果集
如果仍希望仅使用SQL查询,则更喜欢使用:
有枢轴子句的情况:
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
您希望它作为列还是所有时间列的逗号分隔值也适合您的要求?如果我们使用
pivot
,您对每个数字的硬编码值满意吗?每个数字001
的行是未知的吗?我想提一点,我认为我们也可以在pivoting子句中使用相同的行号,而不是time列。(Listag:可以获得4000个字符的限制)是的,也可以@Sujitmohanty30,但星号已经足够了:)
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