【问题标题】:How to convert column into rows in oracle 10goracle 10g如何将列转换为行
【发布时间】:2016-02-23 09:01:27
【问题描述】:

假设我有一个 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

如何编写查询?

【问题讨论】:

  • 看看PIVOT
  • 列的标准是什么?每个月总会有 3 次约会吗?会一直是JanFeb 还是其他月份?
  • Aleksej,在 PIVOT 中您必须使用聚合...但他需要保留所有值 =( 我不确定 PIVOT 在这种情况下是否有帮助
  • @SkyWalker 为什么不呢?不要分组,而是聚合,因此考虑所有值。

标签: sql oracle oracle10g pivot


【解决方案1】:

使用 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 PIVOTMAX + 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"

【讨论】:

    【解决方案2】:
    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 
    

    【讨论】:

      猜你喜欢
      • 2013-01-12
      • 2021-09-12
      • 1970-01-01
      • 2021-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-21
      • 1970-01-01
      相关资源
      最近更新 更多