2017-03-16 69 views
0

我具有下列 - 简化 - 为表布局:的Oracle SQL骨料行到塔LISTAGG与条件

  • 表块(ID)
  • 表内容(ID,BLOCKID,命令,数据,类型)

content.blockIdblocks.id的外键。这个想法是,在内容表中,一个块有很多不同类型的内容条目。

我现在正在查找一个查询,该查询可以根据blockId提供一个聚合,其中3种不同类型的所有内容条目都连接在一起并放入相应的列中。

我已经开始,发现listagg功能,运作良好,我做了下面的语句,并列出了我一列中的所有内容条目:

SELECT listagg(c.data, ',') WITHIN GROUP (ORDER BY c.order) FROM content c WHERE c.blockId = 330; 

现在连接字符串但是包含了所有的data一列中的块的元素。我想实现的是它根据类型将其放入单独的列中。例如content以下内容会是这样:

  • 1,1,0, “内容1”, “片段”
  • 2,1,1, “内容2”, “大量”
  • 3,1,3, “content4”, “片段”
  • 4,1,2, “content3”, “片段”

现在我想获得作为输出2列,一种是片段和一个是BULK,其中FRAGMENT包含“content1; content3; content4”,BULK包含“content2”

有没有一种有效的方法来实现这一目标?

回答

1

您可以使用case

SELECT listagg(CASE WHEN content = 'FRAGMENT' THEN c.data END, ',') WITHIN GROUP (ORDER BY c.order) as fragments, 
     listagg(CASE WHEN content = 'BULK' THEN c.data END, ',') WITHIN GROUP (ORDER BY c.order) as bulks 
FROM content c 
WHERE c.blockId = 330; 
+0

多数民众赞成在这里,谢谢,你碰巧知道如果我的WHERE不是= 350但是例如> 350是否也有可能获得每块一行?我尝试使用'OVER(PARTITION BY c.blockId)',它现在为每个blockId创建行,但是每个条目连接一行,就像有25个片段有25个行具有相同的内容。 –

+0

@YanickSalzmann。 。 。你应该提出新的问题作为*问题*,而不是*评论*。 –

1

作为替代方案,如果你想让它更加动态,你可以转动的结果。 请注意,这只适用于Oracle 11.R2。 Here's一个例子怎么可能是这样的:

select * from 
(with dataSet as (select 1 idV, 1 bulkid, 0 orderV, 'content1' dataV, 'FRAGMENT' typeV from dual union 
       select 2, 1, 1, 'content2', 'BULK' from dual union 
       select 3, 1, 3, 'content4', 'FRAGMENT' from dual union 
       select 4, 1, 2, 'content3', 'FRAGMENT' from dual) 
select typeV, listagg(dataSet.dataV ,',') WITHIN GROUP (ORDER BY orderV) OVER (PARTITION BY typeV) dataV from dataSet) 
pivot 
(
    max(dataV) 
    for typeV in ('BULK', 'FRAGMENT') 
) 

O/P

Bulk  | FRAGMENT 
----------------- 
content2 | content1,content3,content4 

这里最重要的事情:

OVER (PARTITION BY typeV):这就像一组通过为LISTAGG,concatinating一切都有相同的typeV

for typeV in ('BULK', 'FRAGMENT'):这将收集BULKFRAGMENT的数据,并为每个数据生成单独的列。

max(dataV)只是为了提供一个聚合函数,否则pivot不会工作。