如何在Oracle中为单行中的重复ID返回冗余行

时间:2019-06-04 08:21:14

标签: sql oracle oracle11g pivot listagg

我有一个Audit类的表,我们根据其他表中的某些触发器存储一些信息。

ID,Changed_Column,OldValue,NewValue将可用。 现在有可能使用相同的ID,因为更改后的列将具有不同的值,因此我希望将它们合并成一行并获取数据,这将导致3-4个重复 例如,

ID   ChangedColumn OldValue NewValue
1    Name           Bob     Roy
1    Age            26      28  
1    Section        B       C

现在选择时,它将显示所有行,但我想通过基于ID值的合并进行自我连接和仅检索一条记录

预期结果是

ID   Name               Age           Section     ChangedColumns
1    was :Bob now : Roy was:26 now:28 Was:B now:C Name, Age, Section

2 个答案:

答案 0 :(得分:1)

要对列名称进行分组,可以使用listagg函数。 要将行转换为列,请使用Pivot函数。

with tab as(
  select 1 as id,    'Name' as col,    'Bob' as OldValue ,     'Roy' as NewValue from dual union all
  select 1 as id,    'Age',            '26',      '28' as NewValue from dual union all  
  select 1 as id,    'Section',        'B',       'C' as NewValue from dual 
)
select * 

from (
select id
      ,t.col as col
      ,max('was: '|| t.OldValue || ' now: ' || t.NewValue) as val
      ,listagg(t.col,',') within group(order by t.id) OVER (PARTITION BY null)  as ChangedColumn 
from tab t
group by id,t.col

) 
pivot ( max(val)  for col in('Name','Age','Section'));

db <>提琴here

答案 1 :(得分:1)

使用条件聚合看起来很简单:

select id,
       max(case when col = 'Name' then str end) as name,
       max(case when col = 'Age' then str end) as age,
       max(case when col = 'Section' then str end) as section
from (select t.*, ('was: ' || OldValue || ' now: ' || NewValue) as str
      from t
     ) t
group by id;

Here是db <>小提琴。