【发布时间】:2018-01-09 07:12:32
【问题描述】:
我正在转置表中的键值对并遇到问题。
我正在使用Oracle 12C database。
测试数据如下所示。表是tab1
+---------------------------+
| Name | VAL | ID | grp_id|
+---------------------------+
| a | 3 | 1 | 1 |
| b | 5 | 2 | 1 |
| c | 8 | 3 | 1 |
| c | 9 | 4 | 2 |
+---------------------------+
我的预期结果是
+-------------------------+
| grp_id| a | b | c |
+-------------------------+
| 1 | 3 | 5 | 8 |
| 2 | null | null | 9 |
+-------------------------+
到目前为止我所做的是
with t as(
select row_number() over (partition by grp_id order by grp_id) rn,
name,
grp_id,
lead(val,0) over (partition by grp_id order by grp_id) as a,
lead(val,1) over (partition by grp_id order by grp_id) as b,
lead(val,2) over (partition by grp_id order by grp_id) as c
from tab1 where grp_id in (1,2) and name in ('a', 'b','c')
)
select grp_id,a,b,c from t where rn=1;
当数据一致并且所有grp_id-s 键值对都相同时,此查询工作正常,但如果某个grp_id 缺少某些键,我会得到如下结果错了,不是我所期望的
+----------------------------+
| grp_id| a | b | c |
+----------------------------+
| 1 | 3 | 5 | 8 |
| 2 | 9 | null | null |
+----------------------------+
如何改进查询以使其正常工作?我想避免使用pivot
【问题讨论】:
-
为什么要避开
pivot?另外:a、b和c是唯一的名字吗,或者还有其他名字吗?如果还有其他人,他们是提前知道的,还是只通过先查看数据? (而且,你为什么要这样做——尤其是为什么在 SQL 中?当需要这样做时,实际上并不经常这样做,它通常在报告层中完成,而不是在 SQL 中。) -
@mathguy 我不喜欢
pivot。可以有更多的名字。因此,当这个问题解决后,我将动态获取所有名称,并使用动态 sql 执行它。这需要在SQL中完成,就是这样。 -
如果需要使用动态SQL,显然in SQL不会这样做;这需要 PL/SQL,这与 SQL 完全不同(即使与 SQL 紧密集成)。这也有助于了解为什么您不喜欢
pivot。如果你能学会如何正确使用它会更好;这并不难,真的。如果您需要使用旋转的“旧样式”(如 Gordon 的回答)编写动态 SQL 代码,上帝会帮助您。用pivot写就够糟糕了,没有它就更糟了。祝你好运! -
@mathguy 对我来说,使用数据透视查询变得不必要地复杂。特别是当有很多不同的键时。是的,我知道 SQL 和 PL/SQL 的范围 :) 谢谢。
标签: sql oracle pivot window-functions