2011-08-02 14 views
7

クラスター化されていない一意のインデックスを持つテーブルがあり、このインデックスには列が4つリストされています。私はテーブル内の多数の行を更新したい。私がそうした場合、それらはもはや区別されなくなるので、インデックスのために更新が失敗します。非別の行を削除する

インデックスを無効にして、最も古い重複行を削除したいとします。ここに私のクエリはこれまでのところです:

SELECT t.itemid, t.fieldid, t.version, updated 
FROM dbo.VersionedFields w 
inner JOIN 
(
    SELECT itemid, fieldid, version, COUNT(*) AS QTY 
    FROM dbo.VersionedFields 
    GROUP BY itemid, fieldid, version 
    HAVING COUNT(*) > 1 
) t 
on w.itemid = t.itemid and w.fieldid = t.fieldid and w.version = t.version 

内側の内側の選択は、彼らがそう二倍量が実際にそこにある返します右我々は、削除するレコードの数が、グループに参加します。

参加後、すべてのレコードが表示されますが、削除したいレコードはすべて最古のレコードです。

どうすればいいですか?

答えて

9

SQL(Structured Query Language)と言うが実際にはSQL Server(Microsoftのrelatonalデータベースシステム)を意味し、SQL Server 2005以降を使用している場合は、CTE(Common Table Expression)この目的のために。

ItemId(または列の組み合わせ)でデータをパーティション化し、そのパーティションごとに1から始まるSQL Server番号を他の基準で並べ替えることができます - おそらくversion(または他の列)。

したがって、このような何かを試してみてください。例えば日付(基本的に、あなたには、いくつかの他の基準が注文した、いくつかの基準によって、データを分割し、各パーティションの番号付け、それぞれの新しいパーティションの1で開始している

;WITH PartitionedData AS 
(
    SELECT 
     itemid, fieldid, version, 
     ROW_NUMBER() OVER(PARTITION BY ItemId ORDER BY version DESC) AS 'RowNum' 
    FROM dbo.VersionedFields 
) 
DELETE FROM PartitionedData 
WHERE RowNum > 1 

かバージョン)。

したがって、データの各パーティションについて、「最新の」エントリはRowNum = 1であり、同じパーティションに属する(同じpartitino値を有する)任意の他のエントリは、そのパーティションには多くの行があります。

最新のエントリのみを保持する場合は、RowNumが1より大きいものをすべて削除してください。

4
SQL Server 2005

以上:

WITH q AS 
     (
     SELECT *, 
       ROW_NUMBER() OVER (PARTITION BY itemid, fieldid, version ORDER BY updated DESC) AS rn 
     FROM versionedFields 
     ) 
DELETE 
FROM q 
WHERE rn > 1 
0

ような何か試してみてください:

DELETE FROM dbo.VersionedFields w WHERE w.version < (SELECT MAX(version) FROM dbo.VersionedFields) 

勿論を、あなたがしているフィールドの唯一のバージョンにMAX(バージョン)を制限したいと思います削除したい

0

おそらくthis Stack Overflow answer(重複する行の早い方を削除)を参照する必要があります。

本質的に、この技術では、グループを削除するためにグループの最小ID値を見つけるために、グループ化(またはオプションでウィンドウ処理)を使用します。値<> max(行識別子)の行を削除する方が正確かもしれません。

ので:

  1. ドロップユニークインデックス
  2. ロードデータ
  3. (間違いがある場合は、ロールバックできるように、理想的な取引で)グループ化メカニズムを使用してデータを削除し、その後、
  4. をコミット
  5. インデックスを再作成してください。

大きなテーブルにインデックスを再作成すると時間がかかることに注意してください。

+1

marc_sのソリューションは、それを行うためのエレガントな方法です。 – rorycl

関連する問題