2009-04-09 16 views
1

私はいくつかの重複したエントリを持つテーブルを持っています。私は1つを除いてすべてを捨てて、この最新のものを更新しなければならない。私はこの方法では、一時テーブルとwhile文で試してみた:データベースの大規模な更新を効率的に行うにはどうすればよいですか?

CREATE TABLE #tmp_ImportedData_GenericData 
(
    Id int identity(1,1), 
    tmpCode varchar(255) NULL, 
    tmpAlpha3Code varchar(50) NULL, 
    tmpRelatedYear int NOT NULL, 
    tmpPreviousValue varchar(255) NULL, 
    tmpGrowthRate varchar(255) NULL 
) 

INSERT INTO #tmp_ImportedData_GenericData 
SELECT 
    MCS_ImportedData_GenericData.Code, 
MCS_ImportedData_GenericData.Alpha3Code, 
MCS_ImportedData_GenericData.RelatedYear, 
MCS_ImportedData_GenericData.PreviousValue, 
MCS_ImportedData_GenericData.GrowthRate 
FROM MCS_ImportedData_GenericData 
INNER JOIN 
(
    SELECT CODE, ALPHA3CODE, RELATEDYEAR, COUNT(*) AS NUMROWS 
    FROM MCS_ImportedData_GenericData AS M 
    GROUP BY M.CODE, M.ALPHA3CODE, M.RELATEDYEAR 
    HAVING count(*) > 1 
) AS M2 ON MCS_ImportedData_GenericData.CODE = M2.CODE 
    AND MCS_ImportedData_GenericData.ALPHA3CODE = M2.ALPHA3CODE 
    AND MCS_ImportedData_GenericData.RELATEDYEAR = M2.RELATEDYEAR 
WHERE 
(MCS_ImportedData_GenericData.PreviousValue <> 'INDEFINITO') 

-- SELECT * from #tmp_ImportedData_GenericData 
-- DROP TABLE #tmp_ImportedData_GenericData 

DECLARE @counter int 
DECLARE @rowsCount int 

SET @counter = 1 

SELECT @rowsCount = count(*) from #tmp_ImportedData_GenericData 
-- PRINT @rowsCount 

WHILE @counter < @rowsCount 
BEGIN 
    SELECT 
     @Code = tmpCode, 
     @Alpha3Code = tmpAlpha3Code, 
     @RelatedYear = tmpRelatedYear, 
     @OldValue = tmpPreviousValue, 
     @GrowthRate = tmpGrowthRate 
    FROM 
     #tmp_ImportedData_GenericData 
    WHERE 
     Id = @counter 

    DELETE FROM MCS_ImportedData_GenericData 
    WHERE 
     Code = @Code 
     AND Alpha3Code = @Alpha3Code 
     AND RelatedYear = @RelatedYear 
     AND PreviousValue <> 'INDEFINITO' OR PreviousValue IS NULL 

    UPDATE 
     MCS_ImportedData_GenericData 
     SET 
      PreviousValue = @OldValue, GrowthRate = @GrowthRate 
    WHERE 
     Code = @Code 
     AND Alpha3Code = @Alpha3Code 
     AND RelatedYear = @RelatedYear 
     AND MCS_ImportedData_GenericData.PreviousValue ='INDEFINITO' 

    SET @counter = @counter + 1 
END 

それだけで20000がある場合でも、あまりにも長い時間がかかります - 処理するために、30000行が。

パフォーマンスを向上させるためにいくつかの提案がありますか?

ありがとうございます!

+0

ループを使用しないでください! –

+0

TSQLにはループが含まれていますが、ループには最適化されていません。 – MatBailie

+0

これがMicrosoft SQLサーバー固有の場合は、sqlserverとしてタグを付けてください。まあそれまたは私はあきらめて、単にタグSQLを無視します。 – Thomas

答えて

3
WITH q AS (
     SELECT m.*, ROW_NUMBER() OVER (PARTITION BY CODE, ALPHA3CODE, RELATEDYEAR ORDER BY CASE WHEN PreviousValue = 'INDEFINITO' THEN 1 ELSE 0 END) 
     FROM MCS_ImportedData_GenericData m 
     WHERE PreviousValue <> 'INDEFINITO' 
     ) 
DELETE 
FROM q 
WHERE rn > 1 
1

Quassnoiの答えは、SQL Serverの2005+構文を使用していますので、私は、私はより一般的なものを使用して、私のtuppenceに価値を置くだろうと思って...

すべての重複を削除するには、まず、ではなく "は、オリジナル "の場合、複製されたレコードを互いに区別する方法が必要です。

ソースデータにはID列がありません(あなたはtempテーブルに1つ作成します)。その場合は、2つの選択肢があります。
1.データにID列を追加してから、重複を削除します。
2.「重複しない」データセットを作成し、すべてのデータを削除しますオリジナル、オリジナル

オプション1に戻って、デ重複排除データを挿入するには...(新しく作成されたIDフィールドで)何かのような...

DELETE 
    [data] 
FROM 
    MCS_ImportedData_GenericData AS [data] 
WHERE 
    id > (
     SELECT 
      MIN(id) 
     FROM 
      MCS_ImportedData_GenericData 
     WHERE 
      CODE = [data].CODE 
      AND ALPHA3CODE = [data].ALPHA3CODE 
      AND RELATEDYEAR = [data].RELATEDYEAR 
     ) 

ORである可能性があり

DELETE 
    [data] 
FROM 
    MCS_ImportedData_GenericData AS [data] 
INNER JOIN 
(
    SELECT 
     MIN(id) AS [id], 
     CODE, 
     ALPHA3CODE, 
     RELATEDYEAR 
    FROM 
     MCS_ImportedData_GenericData 
    GROUP BY 
     CODE, 
     ALPHA3CODE, 
     RELATEDYEAR 
) 
AS [original] 
    ON [original].CODE = [data].CODE 
    AND [original].ALPHA3CODE = [data].ALPHA3CODE 
    AND [original].RELATEDYEAR = [data].RELATEDYEAR 
    AND [original].id <> [data].id 
0

正確な答えを投稿するのに完全に使用される構文はわかりませんが、ここではアプローチです。 (例えば。選択値+ 1 ...を識別しながら、

はあなたが保存したい行を特定(例えば。選択値を、... ... ..どこから)

更新ロジックを実行します。..どこに...)

新しいテーブルに挿入してください。

ドロップ元、元に新しい名前を変更し、すべての助成金/シノニムを再作成/トリガ/インデックス/ FKS/...(またはオリジナルを切り捨てて、新しいからの挿入]を選択)

明らかにこれはprety大きなを持っていますオーバーヘッドがありますが、何百万もの行を更新/消去したい場合は、これが最速の方法になります。

関連する問題