簡體   English   中英

Oracle將基於2列最大值的重復數據刪除行

[英]Oracle dedupe rows based on max values of 2 columns in conjunction

想知道是否有人知道使用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)將“重復數據刪除”集自動加入到原始集中以獲取產品信息

有人知道實現這一目標的更有效/更清潔的方法以及更好地處理null的方法嗎?

感謝任何反饋。

在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 FIRSTMAXDENSE_RANK LAST

這是有關此主題的Oracle文檔

因為要處理多個列,所以還應該考慮僅使用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()更快。 測試可以為您提供此信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM