【问题标题】:PL/SQL ORACLE query as ResultPL/SQL ORACLE 查询作为结果
【发布时间】:2016-10-05 07:41:28
【问题描述】:

如何为以下条件编写 SQL 查询

结果必须在 PL/SQL 查询中:

MY_TABLE 和数据如下所示:

|   sl. no | col1 | col2 | col3 |col4    | col5 ---col30| col41|col42|....col50
+------   +------+------ +------ +------+
|    1001 |    50 |  101 |  12   |  40   |
|    1002 |    30 |  250 |  80   |       |
|    1003 |    40 |  150 |  90   |       |
|    1004 |    50 |  250 |  20   |       |
|    1005 |    70 |  300 |  30   | 50    |
|    1006 |    80 |  400 | 

col1, col2,col3,...col30

如果 col 数据可用,我想根据 sl.no(条件为 sl.no)检索 col1..to col30 数据(值)。甲骨文 9I 作为行明智的 仅在 PL/SQL oracle 9i 中 结果如下:

1001 | 50
1001 | 101
1001 | 12
1001 | 40
1002 | 30 
1002 |250
1002 | 80  
1003 | 40
1003 | 150
1003 | 90
1004 | 50
1004 | 250
1004 | 20 
1005 |70
1005 |300
1005 |30
1005 |50
1006 |80
1006 |400

【问题讨论】:

  • 您想反透视您的表吗?为什么要/必须使用 PL/SQL?
  • 感谢 Aleksej 编辑问题。
  • @Alex 现有数据库是 Oracle 9i,语言是 SQL
  • 为什么要存储过程?
  • 什么是“PL/SQL 查询”?

标签: oracle plsql


【解决方案1】:
select * 
from (
  select no, decode( rn, 1, col1, 2, col2, 3, col3, 4, col4, 5, col5, ...., 30, col30) col
  from table_name, (select rownum rn from all_objects where rownum <= 30 )
) 
where col is not null

select * 
from (
  select no, decode( rn, 1, col1, 2, col2, 3, col3, 4, col4, 5, col5, ...., 30, col30) col
  from table_name, (select rownum rn from dual connect by rownum <= 30 )
) 
where col is not null

第二个更好,但我不记得它是否可以在 9i 中使用

【讨论】:

    【解决方案2】:

    要取消 11g 之前的方式,您需要执行以下操作:

    WITH my_table AS (SELECT 1001 sl_no, 50 col1, 101 col2, 12 col3, 40 col4 FROM dual UNION ALL
                      SELECT 1002 sl_no, 30 col1, 250 col2, 80 col3, NULL col4 FROM dual UNION ALL
                      SELECT 1003 sl_no, 40 col1, 150 col2, 90 col3, NULL col4 FROM dual UNION ALL
                      SELECT 1004 sl_no, 50 col1, 250 col2, 20 col3, NULL col4 FROM dual UNION ALL
                      SELECT 1005 sl_no, 70 col1, 300 col2, 30 col3, 50 col4 FROM dual UNION ALL
                      SELECT 1006 sl_no, 80 col1, 400 col2, NULL col3, NULL col4 FROM dual),
            dummy AS (SELECT LEVEL lvl
                      FROM   dual
                      CONNECT BY LEVEL <= 4 -- number of columns to unpivot
                      ),
           results AS (SELECT mt.sl_no,
                              d.lvl,
                              CASE WHEN d.lvl = 1 THEN 'COL1'
                                   WHEN d.lvl = 2 THEN 'COL2'
                                   WHEN d.lvl = 3 THEN 'COL3'
                                   WHEN d.lvl = 4 THEN 'COL4'
                              END col_name,
                              CASE WHEN d.lvl = 1 THEN col1
                                   WHEN d.lvl = 2 THEN col2
                                   WHEN d.lvl = 3 THEN col3
                                   WHEN d.lvl = 4 THEN col4
                              END col_value
                       FROM   my_table mt
                              CROSS JOIN dummy d)
    SELECT sl_no,
           col_name,
           col_value
    FROM   results
    WHERE  col_value IS NOT NULL
    ORDER BY sl_no, lvl;
    
         SL_NO COL_NAME  COL_VALUE
    ---------- -------- ----------
          1001 COL1             50
          1001 COL2            101
          1001 COL3             12
          1001 COL4             40
          1002 COL1             30
          1002 COL2            250
          1002 COL3             80
          1003 COL1             40
          1003 COL2            150
          1003 COL3             90
          1004 COL1             50
          1004 COL2            250
          1004 COL3             20
          1005 COL1             70
          1005 COL2            300
          1005 COL3             30
          1005 COL4             50
          1006 COL1             80
          1006 COL2            400
    

    dummy 子查询用于生成与要取消透视的列数相同的一组行。在您的示例中,它是 4。

    然后我们将其交叉连接到表中 - 这意味着表中的每一行都重复了 4 次 - 每一列都将被取消透视。

    一旦我们有了这个,我们说“在第一行显示第一列,第二行显示第二列,第三行显示第三列,等等......”

    我还包括一个列,其中列出了相应值来自的列名;我知道您没有在问题中询问此信息,但它通常是必需的,而且很容易生成。

    取消透视列后,我们将删除所有为空的值。

    【讨论】:

      猜你喜欢
      • 2012-10-26
      • 1970-01-01
      • 2017-03-24
      • 2011-02-02
      • 2023-02-25
      • 1970-01-01
      • 1970-01-01
      • 2021-02-04
      • 2010-11-03
      相关资源
      最近更新 更多