标准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 )
)
答案 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