想知道是否有人知道使用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”设置为原始集合以获取产品信息
有没有人知道更有效/更清晰的方法来实现这一点以及更好地处理空值的方法?
感谢任何反馈。
答案 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_RANK
和LAST
:在GROUP BY
内,此语法显示为聚合函数(如SUM,AVG) ...)。
ORDER BY
给出排序(此处为transactionid和batchid)DENSE_RANK LAST
表示您将关注此排序的最后一行(您可以确实有几行具有相同的排名)MAX
获取这些排名靠前的行中的最大值。大多数情况下,你只有一行,所以MAX
看起来没用,但事实并非如此。因此,您经常会看到MIN
和DENSE_RANK FIRST
,或MAX
和DENSE_RANK LAST
。答案 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()
要快。测试可以为您提供此信息。