0

Order と OrderLine の 2 つのテーブルがあります。Order にはヘッダー情報が含まれており、1 対多の関係の 1 つの側面です。OrderLine には、注文を構成する行が含まれており、多面です。

3 つの注文があり、それぞれに独自の ID がありますが、それぞれの注文行データは同一であり、グループ内のすべてのレコードが同一である場合に限り、重複と見なします。

これには CheckSum_Agg を使用してみましたが、多数の誤検知が発生し、正確な重複ではないレコードが削除されます。

厄介で面倒なネストされたカーソルを回避しようとしています。

何か案は?

編集後: --CheckSum_Agg によって返される誤検知の例...

Create Table #OrderLine(OrderId Int,ProductTypeId Int,ProductId Int);
Insert Into #OrderLine(OrderId,ProductTypeId,ProductId)
Values(1,1,5),(1,2,6),(2,1,6),(2,2,5)

Select CHECKSUM_Agg(ProductTypeId),CHECKSUM_Agg(ProductId)
From #OrderLine
Group By OrderId

Drop Table #OrderLine
4

2 に答える 2

1

CheckSum_Agg は良いスタートだと思います。おそらく、1 つの列でのみ CheckSum_Agg を実行しています。関心のある列ごとに 1 つの CheckSum_Agg を実行すると、すべての重複を見つけることができます。おそらく、CheckSum_Agg の適用に関心がない唯一の列は、OrderLine.id と OrderLine.OrderId です。

2 つの順序が同じかどうかを行ごとにチェックするクエリを次に示します。

with o as (
  select distinct orderid from orderline)
, ol as (select * from orderline)
select o1.orderid as o1, o2.orderid as o2
from o o1, o o2 
where o1.orderid <> o2.orderid and
0= (select count(*) 
          from (select * from ol where ol.orderid = o1.orderid) ol1 
          full outer join 
            (select * from ol where ol.orderid = o2.orderid) ol2 
            on ol1.producttypeid = ol2.producttypeid
            and ol1.productid = ol2.productid
          where (ol2.orderid is null or ol1.orderid is null))

これが実際の動作を示すフィドルです: http://sqlfiddle.com/#!3/359e5/8

ここでの考え方は、オーダーのすべてのペア (o1、o2) を取得し、o1 のオーダーライン ol1 を o2 のオーダーライン ol2 に突き合わせて、それらが一致しているかどうかを確認することです。それらがすべて一致する場合、それらは互いに重複しています。

これはおそらく非常にコストのかかる操作です。これを高速化するために、完全な外部結合基準のすべての列を持つインデックスをお勧めします。

于 2013-06-29T15:22:59.463 に答える
0

テーブルで重複を許可する場合は、簡単に削除できるように代理キーを作成することをお勧めします。一意の制約を使用して、そもそもそれらを許可しない方がよいでしょう。しかし、これをきれいにしてみてください。

Create Table #OrderLine(Pk INT IDENTITY PRIMARY KEY, OrderId Int,ProductTypeId Int,ProductId Int);
Insert Into #OrderLine(OrderId,ProductTypeId,ProductId)
Values(1,1,5),(1,2,6),(2,1,6),(2,2,5),(1,1,5), (1,1,5)

--check
SELECT * FROM #OrderLine

--any dupes?
SELECT * FROM #OrderLine WHERE Pk NOT IN (
    Select Min(Pk)
    From #OrderLine
    Group By OrderId,ProductTypeId,ProductId
)

--delete the dupes
DELETE FROM #OrderLine WHERE Pk NOT IN (
    Select Min(Pk)
    From #OrderLine
    Group By OrderId,ProductTypeId,ProductId
)

--check
SELECT * FROM #OrderLine

Drop Table #OrderLine
于 2013-07-02T23:41:07.850 に答える