使用Listagg时数据重复

时间:2019-01-01 03:35:36

标签: sql oracle

我已经在这个问题上尝试了许多小时,我的数据(ONHAND NUM,PO)一直显示重复的数据,请参考下面的代码。顺便说一句,如果我删除下面的代码,那么我的ONHAND NUM&PO将不再重复,因此我认为这些代码有问题。请协助。谢谢。

    select
listagg(OH.ONHAND_REF,', ')within group(order by ES.SHPMNT_REF) as "Onhand Num",
listagg(PO.PO_ALL_TRACES,', ')within group(order by PO.PO_ALL_TRACES) as "PO"
from BRDB.EXPORT_SHIPMENT ES 
left outer join EXPORT_ONHAND OH on ES.SHPMNT_REF = OH.SHPMNT_REF
left outer join VW_EXPORT_TRACE_PO PO on PO.FILE_NO = OH.ONHAND_REF
left outer join EXPORT_SHPMNT_CTNR CTNR on CTNR.SHPMNT_REF = ES.SHPMNT_REF
group by ES.SHPMNT_REF

如果我删除以下代码,则我的数据看起来将没有重复

  left outer join BRDB.EXPORT_SHPMNT_CTNR CTNR on CTNR.SHPMNT_REF = ES.SHPMNT_REF

我收到的结果如下

Onhand Num          PO
555,555,555         P0001,P0001,P0001
666,777,666,777     P0002,P0003,P0002,P0003

我想要的结果

Onhand Num      PO
 555            P0001
 666,777        P0002,P0003

1 个答案:

答案 0 :(得分:1)

很遗憾,listagg()不支持distinct选项。您可以使用窗口函数或通过沿每个维度进行预聚合来解决此问题。后一种方法效率更高,但是由于没有示例数据,我不愿提出一个具体的查询。

因此,一种足够简单的方法是使用row_number()listagg()忽略NULL值的事实:

select x.SHPMNT_REF,
       listagg(case when seqnum_ohr = 1 then x.ONHAND_REF end, ', '
              ) within group (order by x.SHPMNT_REF) as onhand_numbers,
       listagg(case when seqnum_pat = 1 then x.PO_ALL_TRACES end, ', '
              ) within group (order by x.PO_ALL_TRACES) as pos
from (select ES.SHPMNT_REF, PO.PO_ALL_TRACES, OH.ONHAND_REF,
             row_number() over (partition by ES.SHPMNT_REF, PO.PO_ALL_TRACES order by ES.SHPMNT_REF) as seqnum_pat,
             row_number() over (partition by ES.SHPMNT_REF, OH.ONHAND_REF order by ES.SHPMNT_REF) as seqnum_ohr
      from BRDB.EXPORT_SHIPMENT ES left outer join 
           EXPORT_ONHAND OH
           on ES.SHPMNT_REF = OH.SHPMNT_REF left outer join
           VW_EXPORT_TRACE_PO PO
           on PO.FILE_NO = OH.ONHAND_REF left outer join
           EXPORT_SHPMNT_CTNR CTNR
           on CTNR.SHPMNT_REF = ES.SHPMNT_REF
     ) x
group by x.SHPMNT_REF;

请注意,我还将SHPMNT_REF包括在SELECT中。按该列进行汇总时,这似乎是一种好习惯。当然,您不需要包含它。

我还更改了列别名,因此它们不需要转义符(双引号)。必须转义标识符只会使查询难以编写和阅读。