在PIVOT的FOR子句中使用子选择?

时间:2016-09-01 20:17:02

标签: oracle oracle11g

标准PIVOT语法使用静态FOR列表:

SELECT  *
FROM    (
  SELECT log_id, event_id, event_time
  FROM   patient_events
  WHERE  event_id IN (10,20,30,40,50)
) v
PIVOT (
  max(event_time) event_time
  FOR event_id IN( 10,20,30,40,50 )
)

有没有办法让这种动态变化?

我知道WHERE子句中的子选择可行,但我可以在FOR中使用吗?

SELECT  *
FROM    (
  SELECT log_id, event_id, event_time
  FROM   patient_events
  WHERE  event_id IN ( sub-select to generate list of IDs )
) v
PIVOT (
  max(event_time) event_time
  FOR event_id IN( sub-select to generate list of IDs )
)

2 个答案:

答案 0 :(得分:2)

你不能使用纯SQL,但由于建议的原因,我不能完全思考 - 并不是说​​IN语句需要被命令,它是不是必须常量

当给出查询时,数据库需要知道结果集的形状,并且形状需要在查询之间保持一致(假设没有发生可能影响它的其他DDL操作)。对于PIVOT查询,结果的形状由IN子句定义 - 每个条目成为一个列,其数据类型对应于聚合子句。

假设您允许IN子句的子选择,那么您可以通过执行DML操作来改变结果集的形状。想象一下您的子选择工作并获得系统已知的所有ref cursor的列表 - 通过将新记录插入到子选择的任何驱动器中,即使没有发生DDL,您的查询也会返回不同数量的列

现在我们被卡住了 - 任何构建在该查询上的视图都是无效的,因为它的形状与查询的形状不匹配,但Oracle无法知道它是& #39; s无效,因为它所依赖的对象都没有被DDL更改。

根据您消耗结果的位置,动态SQL是您唯一的选择 - 在应用程序级别(自己构建IN列表)或通过数据库函数中的{{1}}或过程

答案 1 :(得分:1)

有趣的问题。

从表面上看,它不应该起作用,因为必须订购值列表(将成为列名)。对于" IN"而不是这种情况。 WHERE子句中的列表。但也许它可以在子SELECT中使用ORDER BY条件?

不幸的是,没有。这很容易测试。有或没有ORDER BY得到相同的错误消息。 (如果IN列表只有10,20,30,40 - DEPT表中的实际部门编号,则查询工作正常。)使用标准SCOTT模式中的表。

SQL> select deptno from scott.dept;

    DEPTNO
----------
        10
        20
        30
        40
4 rows selected.

SQL> select * from (
  2    select sal, deptno
  3    from scott.emp
  4  )
  5  pivot (sum(sal) as total_sal
  6         for deptno in (10, 20, 30, 40))
  7  ;

10_TOTAL_SAL 20_TOTAL_SAL 30_TOTAL_SAL 40_TOTAL_SAL
------------ ------------ ------------ ------------
        8750        10875         9400

1 row selected.

SQL> select * from (
  2    select sal, deptno
  3    from scott.emp
  4  )
  5  pivot (sum(sal) as total_sal
  6         for deptno in (select deptno from scott.dept order by deptno))
  7  ;
       for deptno in (select deptno from scott.dept order by deptno))
                      *
ERROR at line 6:
ORA-00936: missing expression