Oracle根据最多2列的最大值重复删除行

时间:2014-04-01 10:35:06

标签: sql oracle duplicates max

想知道是否有人知道使用Oracle SQL基于2个属性的最大值一起在大型数据集中重复记录记录的有效方法。

在下面的假设示例中,我希望首先选择最大的transactionid来删除所有重复的COMPANYID / CHILD ID对。有效负载ID仍有重复的地方,最大BATCHID。

注意:transactionID和batchID可能具有空值(预期为最低值)

表:交易

<p> CompanyID| ChildID | transactionid| BatchID | Product Details </P>
<p> ABC         EFG       306                    Product1 </p>
<p>ABC         EFG       306          54        Product2</p>
<p>ZXY         BFG       405          003       Product1</p>
<p>ZXY         BFG       405          004       Product2</p>
<p>ZXY         BFG       407                    Product3</p>

预期结果:

<p>ABC | EFG | 306 | 54 | Product 2  --selected on basis of highest transactionid and batchid </P>
<p>ZXY | BFG | 405 | 407 | Product 3 --selected on basis of highest transactionid </p>

我简单地设想: 1)在transactionid上使用max函数并将结果子化,以使batchID最大化 2)自我加入“de-duped”设置为原始集合以获取产品信息

有没有人知道更有效/更清晰的方法来实现这一点以及更好地处理空值的方法?

感谢任何反馈。

2 个答案:

答案 0 :(得分:2)

从Oracle 11g开始,您可以使用这种请求:

with w(CompanyID, ChildID, transactionid, BatchID, Product_Details) as
(
  select 'ABC', 'EFG', 306, null, 'Product1 ' from dual
  union all
  select 'ABC', 'EFG', 306, 54, 'Product2' from dual
  union all
  select 'ZXY', 'BFG', 405, 003, 'Product1' from dual
  union all
  select 'ZXY', 'BFG', 405, 004, 'Product2' from dual
  union all
  select 'ZXY', 'BFG', 407, null, 'Product3' from dual
)
select w.CompanyID,
       w.ChildID,
       max(w.transactionid)   keep (dense_rank last order by nvl(w.transactionid, 0), nvl(w.batchid, 0)) max_transactionid,
       max(w.batchid)         keep (dense_rank last order by nvl(w.transactionid, 0), nvl(w.batchid, 0)) max_batchid,
       max(w.Product_Details) keep (dense_rank last order by nvl(w.transactionid, 0), nvl(w.batchid, 0)) max_Product_Details
from w
group by w.CompanyID, w.ChildID
;

nvl函数允许您处理空案例。这是输出(不符合你的要求,但我按照你的理解做了你的要求):

COMPANYID    CHILDID    MAX_TRANSACTIONID    MAX_BATCHID    MAX_PRODUCT_DETAILS
ABC          EFG        306                  54             Product2
ZXY          BFG        407                                 Product3

编辑:让我尝试进一步解释DENSE_RANKLAST:在GROUP BY内,此语法显示为聚合函数(如SUM,AVG) ...)。

  • 在一个组中,ORDER BY给出排序(此处为transactionid和batchid)
  • 然后DENSE_RANK LAST表示您将关注此排序的最后一行(您可以确实有几行具有相同的排名)
  • MAX获取这些排名靠前的行中的最大值。大多数情况下,你只有一行,所以MAX看起来没用,但事实并非如此。因此,您经常会看到MINDENSE_RANK FIRST,或MAXDENSE_RANK LAST

这是the Oracle doc on this subject

答案 1 :(得分:1)

因为您要处理多个列,所以您还应该考虑使用row_number()

select t.*
from (select t.*,
             row_number() over (partition by CompanyId, ChildId
                                order by transactionid desc nulls last, BatchID desc nulls last
                               ) as seqnum
      from t
     ) t
where seqnum = 1;

keep/dense_rank方法很快。我不确定这样做多次比使用row_number()要快。测试可以为您提供此信息。