为了账号安全,请及时绑定邮箱和手机立即绑定

在Oracle中将行动态转换为列

/ 猿问

在Oracle中将行动态转换为列

绝地无双 2019-12-03 10:45:55

我有以下名为_kv的Oracle 10g表:


select * from _kv


ID       K       V

----     -----   -----

  1      name    Bob

  1      age     30

  1      gender  male

  2      name    Susan

  2      status  married

我想使用普通SQL(而不是PL / SQL)将键转换为列,以便生成的表如下所示:


ID       NAME    AGE    GENDER  STATUS

----     -----   -----  ------  --------

  1      Bob      30     male 

  2      Susan                   married

该查询应具有与表中K存在的unique一样多的列(数量不多)

在运行查询之前,无法知道可能存在哪些列。

我试图避免运行初始查询以编程方式构建最终查询。

空白单元格可以为null或空字符串,并不重要。

我正在使用Oracle 10g,但是11g解决方案也可以。

当您知道您的透视列可能被称为什么时,这里有很多示例,但是我只是找不到适用于Oracle的通用透视解决方案。


谢谢!


查看完整描述

3 回答

?
慕的地10843

Oracle 11g提供了PIVOT您所需的操作。


Oracle 11g解决方案


select * from

(select id, k, v from _kv) 

pivot(max(v) for k in ('name', 'age', 'gender', 'status')

(注意:我没有11g的副本可以对此进行测试,因此我尚未验证其功能)


我从以下网址获得了此解决方案:http : //orafaq.com/wiki/PIVOT


编辑-枢轴xml选项(也是Oracle 11g)

显然pivot xml,当您不知道可能需要的所有可能的列标题时,还有一个选项。(请参阅位于页面底部附近的XML TYPE部分,该部分位于http://www.oracle.com/technetwork/articles/sql/11g-pivot-097235.html)


select * from

(select id, k, v from _kv) 

pivot xml (max(v)

for k in (any) )

(注意:和以前一样,我没有11g的副本可用于测试此功能,因此我尚未验证其功能)


Edit2:v将pivotand pivot xml语句更改为,max(v)因为应该按照注释之一中的说明对其进行汇总。我还添加了in子句,它不是的可选pivot。当然,必须在in子句中指定值会破坏实现完全动态的数据透视表/交叉表查询的目的,就像该问题的发布者所希望的那样。


查看完整回答
反对 回复 2019-12-03
?
料青山看我应如是

为了处理可能存在多个值(在您的示例中为v)的情况,我使用PIVOT和LISTAGG:


SELECT * FROM

(

  SELECT id, k, v

  FROM _kv 

)

PIVOT 

(

  LISTAGG(v ,',') 

  WITHIN GROUP (ORDER BY k) 

  FOR k IN ('name', 'age','gender','status')

)

ORDER BY id;

由于需要动态值,因此在调用透视表语句之前,请使用动态SQL并传递通过在表数据上运行select所确定的值。


查看完整回答
反对 回复 2019-12-03
?
拉风的咖菲猫

碰巧要完成一项任务。下面对我来说适用于11g的测试:


select * from

(

  select ID, COUNTRY_NAME, TOTAL_COUNT from ONE_TABLE 

pivot(

  SUM(TOTAL_COUNT) for COUNTRY_NAME in (

    'Canada', 'USA', 'Mexico'

  )

);


查看完整回答
反对 回复 2019-12-03

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信