2

テーブルで重複するエントリを削除する検索を行っていたところ、次のような例が見つかりました。

CREATE TABLE Suppliers
(
  Id int identity (1,1),
  CompanyTitle nvarchar(1000),
  ContactName nvarchar(100),
  LastContactDate datetime
)

INSERT Suppliers VALUES (N'Melody Music Instruments',N'James Manning', '20090623 10:15')
INSERT Suppliers VALUES (N'Blue Jazz',N'Mike Clark', '20090720 15:40')
INSERT Suppliers VALUES (N'Top Music',N'Katy Swan', '20090827 18:00')
INSERT Suppliers VALUES (N'Blue Jazz',N'Mike Clark', '20090806 10:00')
INSERT Suppliers VALUES (N'Melody Music Instruments',N'James Brown', '20080121 11:20')
INSERT Suppliers VALUES (N'Top Music',N'Katy Perry', '20090825 14:00')
INSERT Suppliers VALUES (N'Top Music',N'Katy Perry', '20090825 14:00')


WITH Duplicate AS 
(
SELECT
  RN = ROW_NUMBER() OVER (PARTITION BY CompanyTitle ORDER BY LastContactDate DESC)
FROM Suppliers
)
delete from Duplicate where RN > 1

CTE は次のようなものを返し、値が 1 より大きい場合は削除します。

RN
--
1
2
1
2
1
2
3

私が理解できなかったのは、どのエントリが削除されるかを理解する方法です。この例では、重複するエントリ数を返すだけです。

実際の例: http://www.sqlfiddle.com/#!3/d84b6/20

4

3 に答える 3

4

サンプル テーブルはヒープです (クラスター化インデックスがないことを意味します)。

例の実行計画を見ると、それBmk1000がリーフ レベル テーブル スキャンの出力列リストにあり、この列が計画内のすべての演算子にわたって演算子まで渡されていることがわかりますDELETE

Bmk1000行が見つかる場所を一意に識別するブックマークです (ヒープの行識別子には、行の File:Page:Slot の場所が含まれます)。これにより、DELETEオペレータはこれを使用して必要な行を見つけることができます。

テーブルにクラスター化インデックスがある場合、ブックマークではなく、クラスター化インデックス キー列がこの方法で渡されたことがわかります。

于 2013-02-19T23:15:11.390 に答える
1

あなたの質問は何ですか?行番号が1より大きいものはすべて削除されます。。。コードは非常に明示的RN > 1です。

各CompanyTitleから始めて、行に行番号を割り当てます。最新の連絡日を持つ行の値は1になります。

したがって、このコードは、各CompanyTitleの最新の連絡先よりも古いものをすべて削除します。

于 2013-02-19T21:32:25.227 に答える
1

PARTITION BY および ORDER BY 句は、削除される行を制御します。CTE を少し拡大すると、これがどのように機能するかがより明確になります。(PostgreSQL 構文)

WITH Duplicate AS 
(
  SELECT
    ROW_NUMBER() OVER (PARTITION BY CompanyTitle ORDER BY LastContactDate DESC),
    CompanyTitle, 
    LastContactDate 
  FROM Suppliers
)
select * 
from Duplicate

(読みやすくするために、以下に空行を追加します。)

1  Blue Jazz                    2009-08-06 10:00:00
2  Blue Jazz                    2009-07-20 15:40:00

1  Melody Music Instruments     2009-06-23 10:15:00
2  Melody Music Instruments     2008-01-21 11:20:00

1  Top Music                    2009-08-27 18:00:00
2  Top Music                    2009-08-25 14:00:00
3  Top Music                    2009-08-25 14:00:00

PARTITION 句は、同一の CompanyTitle 値をまとめて保持します。ORDER BY 句は、CompanyTitle の値が同じ行をLastContactDate で並べ替えます。降順でソートされるため、各 CompanyTitle の最新の行には常に 1 の番号が付けられます。

したがって、 CompanyTitle ごとに最新の行を除くすべての行を削除するには、行番号が 1 より大きいすべての行を削除します。

于 2013-02-19T22:46:45.107 に答える