Oracle SQL将行聚合到具有条件的列listagg中

时间:2017-03-16 12:10:38

标签: sql oracle

我正在使用以下 - 简化 - 表格布局:

  • TABLE blocks(id)
  • TABLE内容(id,blockId,顺序,数据,类型)

setupNavigationBar(title: "Your Order") content.blockId的外键。我们的想法是,在内容表中,您有许多内容条目,其中一个块具有不同的类型。

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

我已经开始并找到了运行良好的blocks.id函数,我做了以下语句并列出了列中的所有内容条目:

listagg

现在,连接字符串包含一列中块的所有SELECT listagg(c.data, ',') WITHIN GROUP (ORDER BY c.order) FROM content c WHERE c.blockId = 330; 个元素。我想要实现的是根据类型将其放入单独的列中。例如,data的以下内容将如下所示:

  • 1,1,0," content1"," FRAGMENT"
  • 2,1,1," content2"," BULK"
  • 3,1,3," content4"," FRAGMENT"
  • 4,1,2," content3"," FRAGMENT"

现在我希望输出2列,一个是FRAGMENT,一个是BULK,其中FRAGMENT包含" content1; content3; content4"和BULK包含" content2"

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

2 个答案:

答案 0 :(得分:2)

您可以使用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;

答案 1 :(得分:2)

作为替代方案,如果您希望它更具动态性,您可以转动结果。 请注意,这仅适用于Oracle 11.R2。以下是一个示例:

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的group by一样,整合了所有具有相同typeV的内容。

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

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