在Oracle中动态地将行旋转到列中

ojo*_*lva 25 sql oracle pivot oracle10g

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

select * from _kv

ID       K       V
----     -----   -----
  1      name    Bob
  1      age     30
  1      gender  male
  2      name    Susan
  2      status  married
Run Code Online (Sandbox Code Playgroud)

我想使用纯SQL(而不是PL/SQL)将我的密钥转换为列,以便生成的表看起来像这样:

ID       NAME    AGE    GENDER  STATUS
----     -----   -----  ------  --------
  1      Bob      30     male 
  2      Susan                   married
Run Code Online (Sandbox Code Playgroud)
  • 查询应该具有与表中K存在的唯一s 一样多的列(没有那么多)
  • 在运行查询之前无法知道可能存在哪些列.
  • 我试图避免运行初始查询以编程方式构建最终查询.
  • 空白单元格可能为空或空字符串,并不重要.
  • 我正在使用Oracle 10g,但11g解决方案也可以.

当您知道可以调用您的透视列时,有很多示例,但我找不到Oracle的通用透视解决方案.

谢谢!

dav*_*ave 31

Oracle 11g提供了一个可以满足PIVOT您需求的操作.

Oracle 11g解决方案

select * from
(select id, k, v from _kv) 
pivot(max(v) for k in ('name', 'age', 'gender', 'status')
Run Code Online (Sandbox Code Playgroud)

(注意:我没有11g的副本来测试这个,所以我还没有验证它的功能)

我从http://orafaq.com/wiki/PIVOT获得了这个解决方案

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

select * from
(select id, k, v from _kv) 
pivot xml (max(v)
for k in (any) )
Run Code Online (Sandbox Code Playgroud)

(注意:和以前一样,我没有11g的副本来测试这个,所以我还没有验证它的功能)

Edit2:vpivotpivot xml语句中更改,max(v)因为它应该按照其中一条注释中的说明进行聚合.我还添加了in不可选的子句pivot.当然,必须在in子句中指定值会使得完全动态的pivot/crosstab查询的目标失败,就像这个问题的海报一样.

  • xml pivot在v:`(max(v)for k in(any))`中添加了一个聚合,但结果是一个名为`K_XML`的clob列中的xml - 不是我需要的. (2认同)

eni*_*ger 6

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

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;
Run Code Online (Sandbox Code Playgroud)

由于您需要动态值,因此在调用pivot语句之前,请使用动态SQL并传入在表数据上运行select所确定的值.


Her*_* Yu 5

发生在枢轴上的任务.以下对11g的测试仅适用于我:

select * from
(
  select ID, COUNTRY_NAME, TOTAL_COUNT from ONE_TABLE 
) 
pivot(
  SUM(TOTAL_COUNT) for COUNTRY_NAME in (
    'Canada', 'USA', 'Mexico'
  )
);
Run Code Online (Sandbox Code Playgroud)