SQL - Oracle - 具有动态数据的数据透视表

Posted

技术标签:

【中文标题】SQL - Oracle - 具有动态数据的数据透视表【英文标题】:SQL - Oracle - pivoting table with dynamic data 【发布时间】:2018-05-17 14:22:55 【问题描述】:

在 Oracle DB 上工作,我有以下 'GROUPS' 表:

ID    NAME    LAYER    VALUE
1     A       L1       100
1     A       L2       200
1     A       L3       300
1     A       L4       400
1     A       L5       500
2     B       L1       111
2     B       L2       222
2     B       L3       333
2     B       L4       444
2     B       L5       555
2     B       L6       666
2     B       L7       777

**ID** - identifies the group.
**NAME** - group's name.
**LAYER** - a layer in the group ; a group consists of N layers.
**VALUE** - the value of a given layer in a given group.

此表中的数据代表 2 个元素,可通过 ID(1 和 2)区分。 每组包含 N 层(对于第 1 组,L1-L5;对于第 2 组 L1-L7),每层都有一个值。

我正在尝试创建数据库功能,该功能将透视动态图层数据,因此每个图层将成为一列,并且它的行将是表中每个唯一 ID (1,2) 的值。

ID    NAME    L1    L2    L3    L4    L5    L6    L7    
1     A       100   200   300   400   500   
2     B       111   222   333   444   555   666   777

请注意,这些组具有不同的层数。

所述功能可以是视图、函数或存储过程 - 任何东西,只要由数据库处理即可。

非常感谢您的帮助!

尼尔

【问题讨论】:

层数是固定的吗?我的意思是 L1 - L7,总共 7 个? 每组的层数是动态的,可以是 1 到 30 之间的任意值 请看一下这篇博文——它是在 SQL Server 中完成的,但仍然应该有帮助 thesqlserverdeveloper.blogspot.com/2018/02/… 感谢@DanielMarcus - 会看看! 在这里查看动态数据透视的示例:***.com/questions/15491661/… 【参考方案1】:

您可以像这样构建动态查询:

decalre
    sqlstr VARCHAR2(30000);
    cur SYS_REFCURSOR;
begin

    SELECT SELECT LISTAGG(''''||LAYER||''' AS '||layer, ',') WITHIN GROUP (ORDER BY LAYER)
    INTO sqlstr 
    FROM (SELECT LAYER FROM your_table GROUP BY LAYER);

    sqlstr := 'SELECT * FROM your_table PIVOT (MIN(VALUESS) FOR layers IN ('||sqlstr||'))';
    DBMS_OUTPUT.PUT_LINE(sqlstr);

    OPEN cur FOR sqlstr;
    ...

end;   

【讨论】:

听起来很有趣 - 会调查它。谢谢@Wernfried Domscheit!【参考方案2】:

使用 Oracle 的 PIVOT 函数,您可以这样做,您必须将所有 30 个值的列表放在 PIVOT 部分中,我已经完成了 L7:

SQL> 
SQL> WITH cte_table(IDS, NAMES, LAYERS, VALUESS) as (
  2      SELECT 1, 'A', 'L1', 100 from dual union all
  3      SELECT 1, 'A', 'L2', 200 from dual union all
  4      SELECT 1, 'A', 'L3', 300 from dual union all
  5      SELECT 1, 'A', 'L4', 400 from dual union all
  6      SELECT 1, 'A', 'L5', 500 from dual union all
  7      SELECT 2, 'B', 'L1', 111 from dual union all
  8      SELECT 2, 'B', 'L2', 222 from dual union all
  9      SELECT 2, 'B', 'L3', 333 from dual union all
 10      SELECT 2, 'B', 'L4', 444 from dual union all
 11      SELECT 2, 'B', 'L5', 555 from dual union all
 12      SELECT 2, 'B', 'L6', 666 from dual union all
 13      SELECT 2, 'B', 'L7', 777 from dual)
 14  SELECT *
 15    FROM cte_table
 16   PIVOT (MIN(VALUESS) FOR layers IN ('L1' AS "L1", 'L2' AS "L2", 'L3' AS "L3", 'L4' AS "L4", 'L5' AS "L5", 'L6' AS "L6", 'L7' AS "L7")) --list goes here
 17  /

输出:

       IDS NAMES         L1         L2         L3         L4         L5         L6         L7
---------- ----- ---------- ---------- ---------- ---------- ---------- ---------- ----------
         1 A            100        200        300        400        500            
         2 B            111        222        333        444        555        666        777

【讨论】:

感谢@San,但是如果我有 40 个或 100 个呢?我需要的是一种自动执行此任务的方法-目前我正在软件中执行此操作,但我正在寻找一种方法将此任务委托给数据库-这是一种动态情况,因此是硬编码的解决方案无法工作 动态方式无法使用 PIVOT。 您可以生成动态 SQL 来创建 PIVOT 语句,但这很可能很快就会变得一团糟。但是,这是可能的。 没错,你不能只使用PIVOT,你需要编写动态SQL,即使是XML Pivoting你也需要知道列数才能获得有意义的名称。

以上是关于SQL - Oracle - 具有动态数据的数据透视表的主要内容,如果未能解决你的问题,请参考以下文章

将表数据类型从 SQL Server 转换为 Oracle 并将动态 SQL 数据插入到表数据类型

oracle执行动态sql选择脚本并返回表格数据

如何在没有任何视图或任何其他表类型的情况下在 oracle 中创建具有动态列名和动态数据类型的动态表

小弟使用OTL函数,动态拼凑SQL查询oracle数据库数据问题

使用动态列 Oracle SQL 查询的数据

如何实现Oracle数据库中的动态游标