oracle使用distinct listagg

时间:2015-06-23 17:45:23

标签: sql oracle11g correlated-subquery

我有一个有趣的问题,我想弄清楚。我有一个视图,它正在添加一个列。此列是来自其他表的数据透视数据,以形成单行。现在,我需要清除此透视数据中的重复条目。 Listagg非常适合将数据转换为单行,但我需要使其独一无二。虽然我知道如何使它独特,但我正在踩到相关子查询只有1级深度的事实。所以...不确定如何获得一个独特的值列表。如果我不做那么明显就好了,我可以让它工作。谁能在那里工作一些SQL魔法?

示例数据:

drop table test;
drop table test_widget;

create table test (id number, description Varchar2(20));

create table test_widget (widget_id number, test_fk number, widget_type varchar2(20));

insert into test values(1, 'cog');
insert into test values(2, 'wheel');
insert into test values(3, 'spring');

insert into test_widget values(1, 1, 'A');
insert into test_widget values(2, 1, 'A');
insert into test_widget values(3, 1, 'B');
insert into test_widget values(4, 1, 'A');
insert into test_widget values(5, 2, 'C');
insert into test_widget values(6, 2, 'C');
insert into test_widget values(7, 2, 'B');
insert into test_widget values(8, 3, 'A');
insert into test_widget values(9, 3, 'C');
insert into test_widget values(10, 3, 'B');
insert into test_widget values(11, 3, 'B');
insert into test_widget values(12, 3, 'A');

commit;

以下是可用的查询示例,但显示重复数据:

SELECT A.ID
     , A.DESCRIPTION
     , (SELECT LISTAGG (WIDGET_TYPE, ', ') WITHIN GROUP (ORDER BY WIDGET_TYPE)
          FROM TEST_WIDGET
         WHERE TEST_FK = A.ID) widget_types
  FROM TEST A

以下是由于我尝试引用ID的深度而无效的示例:

SELECT A.ID
     , A.DESCRIPTION
     , (SELECT LISTAGG (WIDGET_TYPE, ', ') WITHIN GROUP (ORDER BY WIDGET_TYPE)
          FROM (SELECT DISTINCT WIDGET_TYPE
                  FROM TEST_WIDGET
                 WHERE TEST_FK = A.ID))
          WIDGET_TYPES
  FROM TEST A

这是我想要显示的内容:

1   cog A, B
2   wheel   B, C
3   spring  A, B, C

如果有人知道他们的头顶,那太棒了!否则,我可以发布一些示例create语句来帮助您使用虚拟数据来计算查询。

2 个答案:

答案 0 :(得分:2)

您可以在子查询中应用distinct,它也具有连接 - 避免级别问题:

SELECT ID
     , DESCRIPTION
     , LISTAGG (WIDGET_TYPE, ', ')
         WITHIN GROUP (ORDER BY WIDGET_TYPE) AS widget_types
FROM (
  SELECT DISTINCT A.ID, A.DESCRIPTION, B.WIDGET_TYPE
  FROM TEST A
  JOIN TEST_WIDGET B
  ON B.TEST_FK = A.ID
)
GROUP BY ID, DESCRIPTION
ORDER BY ID;

        ID DESCRIPTION          WIDGET_TYPES       
---------- -------------------- --------------------
         1 cog                  A, B                
         2 wheel                B, C                
         3 spring               A, B, C             

答案 1 :(得分:0)

我使用Pentaho报告编写器和一些不一致的数据处于一种独特的情况。 Pentaho编写者使用Oracle查询数据,但有局限性。数据块是唯一的,但没有以一致的方式分类,所以我在左连接中创建了一个嵌套的listagg,以我想要的方式呈现数据:

             left join
            (
            select  staff_id, listagg(thisThing, ' --- '||chr(10) ) within group (order by this)  as SCHED_1  from
                            (
                            SELECT 
                            staff_id, RPT_STAFF_SHIFTS.ORGANIZATION||': '||listagg( 
                           RPT_STAFF_SHIFTS.DAYS_OF_WEEK 
                            , ',' ) within group (order by BEGIN_DATE desc) 
                            as thisThing
                           FROM "RPT_STAFF_SHIFTS" where "RPT_STAFF_SHIFTS"."END_DATE" is null
                            group by staff_id, organization)
            group by staff_id
            ) schedule_1  on schedule_1.staff_id = "RPT_STAFF"."STAFF_ID"
 where "RPT_STAFF"."STAFF_ID" ='555555'

这是一种与使用嵌套查询不同的方法,但在某些情况下,通过在开发查询时考虑级别问题并采取额外步骤来完全连接结果,它可能会更好。