假设我有Oracle sql查询的结果:
Month Date
----- -----
Jan 10
Jan 15
Jan 20
Feb 11
Feb 16
Feb 25
我想以下列格式显示这些数据:
Jan Jan Jan Feb Feb Feb
10 15 20 11 16 25
如何编写查询?
答案 0 :(得分:2)
使用 PIVOT :
SQL> WITH sample_data AS(
2 SELECT 'Jan' mnth, 10 dt FROM dual UNION ALL
3 SELECT 'Jan' mnth, 15 dt FROM dual UNION ALL
4 SELECT 'Jan' mnth, 20 dt FROM dual UNION ALL
5 SELECT 'Feb' mnth, 11 dt FROM dual UNION ALL
6 SELECT 'Feb' mnth, 16 dt FROM dual UNION ALL
7 SELECT 'Feb' mnth, 25 dt FROM dual
8 )
9 -- end of smaple_data mimicking real table
10 SELECT *
11 FROM
12 (SELECT dt, row_number() OVER(ORDER BY NULL) rn FROM sample_data
13 ) PIVOT (MAX(dt) FOR (rn)
14 IN (1 AS Jan_1, 2 AS jan_2, 3 AS Jan_3, 4 AS Feb_1, 5 Feb_2, 6 Feb_3));
JAN_1 JAN_2 JAN_3 FEB_1 FEB_2 FEB_3
---------- ---------- ---------- ---------- ---------- ----------
10 15 20 11 16 25
Under the hood PIVOT 与 MAX + CASE 相同。您可以在12c
中将Oracle EXPAND_SQL_TEXT 程序添加到 DBMS_UTILITY 程序包中进行检查。
SQL> VARIABLE c CLOB
SQL> BEGIN
2 dbms_utility.expand_sql_text(Q'[WITH sample_data AS(
3 SELECT 'Jan' mnth, 10 dt FROM dual UNION ALL
4 SELECT 'Jan' mnth, 15 dt FROM dual UNION ALL
5 SELECT 'Jan' mnth, 20 dt FROM dual UNION ALL
6 SELECT 'Feb' mnth, 11 dt FROM dual UNION ALL
7 SELECT 'Feb' mnth, 16 dt FROM dual UNION ALL
8 SELECT 'Feb' mnth, 25 dt FROM dual
9 )
10 -- end of smaple_data mimicking real table
11 SELECT *
12 FROM
13 (SELECT dt, row_number() OVER(ORDER BY NULL) rn FROM sample_data
14 ) PIVOT (MAX(dt) FOR (rn)
15 IN (1 AS Jan_1, 2 AS jan_2, 3 AS Jan_3, 4 AS Feb_1, 5 Feb_2, 6 Feb_3))]',:c);
16 END;
17 /
PL/SQL procedure successfully completed.
现在让我们看看Oracle内部实际做了什么:
SQL> set long 100000
SQL> print c
C
--------------------------------------------------------------------------------
SELECT "A1"."JAN_1" "JAN_1",
"A1"."JAN_2" "JAN_2",
"A1"."JAN_3" "JAN_3",
"A1"."FEB_1" "FEB_1",
"A1"."FEB_2" "FEB_2",
"A1"."FEB_3" "FEB_3"
FROM
(SELECT MAX(
CASE WHE N ("A2"."RN"=1)
THEN "A2"."DT"
END ) "JAN_1",
MAX(
CASE
WHEN ("A2"."RN"=2)
THEN " A2"."DT"
END ) "JAN_2",
MAX(
CASE
WHEN ("A2"."RN"=3)
THEN "A2"."DT"
END ) "JAN_3" ,
MAX(
CASE
WHEN ("A2"."RN"=4)
THEN "A2"."DT"
END ) "FEB_1",
MAX(
CASE
WHEN ("A2". "RN"=5)
THEN "A2"."DT"
END ) "FEB_2",
MAX(
CASE
WHEN ("A2"."RN"=6)
THEN "A2"."DT"
END ) "FEB_3"
FROM
(SELECT "A3"."DT" "DT",
ROW_NUMBER() OVER ( ORDER BY NULL) " RN"
FROM (
(SELECT 'Jan' "MNTH",10 "DT" FROM "SYS"."DUAL" "A10"
)
UNION ALL (SE LECT 'Jan' "MNTH",15 "DT" FROM "SYS"."DUAL" "A9")
UNION ALL
(SELECT 'Jan' "MNTH",20 "DT" FROM "SYS"."DUAL" "A8"
)
UNION ALL
(SELECT 'Feb' "MNTH",11 "DT" FROM " SYS"."DUAL" "A7"
)
UNION ALL
(SELECT 'Feb' "MNTH",16 "DT" FROM "SYS"."DUAL" "A6"
)
UNION ALL
(SELECT 'Feb' "MNTH",25 "DT" FROM "SYS"."DUAL" "A5"
)) "A3"
) "A2"
) " A1"
答案 1 :(得分:1)
WITH dates( month, day ) AS (
SELECT 'Jan', 10 FROM DUAL UNION ALL
SELECT 'Jan', 15 FROM DUAL UNION ALL
SELECT 'Jan', 20 FROM DUAL UNION ALL
SELECT 'Feb', 11 FROM DUAL UNION ALL
SELECT 'Feb', 16 FROM DUAL UNION ALL
SELECT 'Feb', 25 FROM DUAL
),
ordered_dates( month, day, seq_no ) AS (
SELECT month,
day,
ROW_NUMBER() OVER ( PARTITION BY month ORDER BY day )
FROM dates
)
SELECT MAX( CASE WHEN month = 'Jan' AND seq_no = 1 THEN day END ) AS "Jan",
MAX( CASE WHEN month = 'Jan' AND seq_no = 2 THEN day END ) AS "Jan",
MAX( CASE WHEN month = 'Jan' AND seq_no = 3 THEN day END ) AS "Jan",
MAX( CASE WHEN month = 'Feb' AND seq_no = 1 THEN day END ) AS "Feb",
MAX( CASE WHEN month = 'Feb' AND seq_no = 2 THEN day END ) AS "Feb",
MAX( CASE WHEN month = 'Feb' AND seq_no = 3 THEN day END ) AS "Feb"
FROM ordered_dates;
<强>输出强>:
Jan Jan Jan Feb Feb Feb
---------- ---------- ---------- ---------- ---------- ----------
10 15 20 11 16 25