0

現在、あるデータベースから別のデータベースにデータを移動することを目的とした DataImport スクリプトに取り組んでいます。私が遭遇した主な問題は、問題のテーブルに多くの重複レコードが含まれており、重複フィールドが製品コード、言語、法律、ブランド名、フォーミュラ、およびバージョンであることです。つまり、データベースに次のものが含まれている可能性があります。

My Test Product, English, UK, Test Brand, Test Formula, 1 (ID 1 - group by には含まれません)
My Test Product, English, UK, Test Brand, Test Formula, 1 (ID 2 - group by には含まれません)
My Test Product, English, UK, Test Brand, Test Formula, 1 (ID 3 - group by には含まれません)
My Test Product, English, UK, Test Brand, Test Formula, 1 (ID 4 - group by には含まれません)

ご覧のとおり、これらのレコードはあらゆる点で同一です。私の問題は、データ ロード スクリプトの一部として、ID が 4 のレコードを保持しながら、ID が 1、2、および 3 のレコードを削除したいということです。飼いたいです。これを行うために、次のように T-SQL スクリプトを作成しました。

-- get the list of items where there is at least one duplicate
DECLARE cDuplicateList CURSOR FOR
SELECT productcode, languageid, legislationid, brandName, versionnumber, formulaid
FROM allproducts
GROUP BY productcode, languageid, legislationid, brandName, versionnumber, formulaid
HAVING COUNT (*) > 1  

OPEN cDuplicateList

FETCH cDuplicateList INTO @productCode, @languageId, @legislationId, @brandName, @versionNumber, @formulaId

-- while there are still duplicates
WHILE @@FETCH_STATUS=0
BEGIN

-- delete from the table where the product ID is in the sub-query, which contains all
-- of the records apart from the last one
DELETE FROM AllProducts 
WHERE productId IN
(
    SELECT productId
    FROM allProducts
    WHERE productCode = @productCode 
        AND (languageId = @languageId OR @languageId IS NULL) 
        AND (legislationId = @legislationId OR @legislationId IS NULL)
        AND (brandName = @brandName OR @brandName IS NULL)
        AND (versionNumber = @versionNumber OR @versionNumber IS NULL)
        AND (formulaId = @formulaId OR @formulaId IS NULL)
    EXCEPT
    SELECT TOP 1 productId
    FROM allProducts
    WHERE productCode = @productCode 
        AND (languageId = @languageId OR @languageId IS NULL) 
        AND (legislationId = @legislationId OR @legislationId IS NULL)
        AND (brandName = @brandName OR @brandName IS NULL)
        AND (versionNumber = @versionNumber OR @versionNumber IS NULL)
        AND (formulaId = @formulaId OR @formulaId IS NULL)
)

FETCH cDuplicateList INTO @productCode, @languageId, @legislationId, @brandName, @versionNumber, @formulaId

END

今、これはうまくいきます-信じられないほど遅く、速くする簡単な方法は考えられません. 同じ機能を維持しながらより高速に実行する方法を知っている人はいますか?

4

3 に答える 3

3

SQL_Server 2005では、既にcommon-table-expressionandを使用できます。ROW_NUMBER

WITH CTE AS
(
    SELECT ProductCode, Language, Legislation, BrandName, Formula, Version,
       RN = ROW_NUMBER() 
                   OVER ( 
                     PARTITION BY productcode, language, legislation, brandname, formula, version 
                     ORDER BY id DESC) 
    FROM dbo.Students
)
DELETE FROM CTE WHERE RN > 1

何を削除するかを確認したい場合は、 に変更DELETEします。SELECT *

于 2013-10-08T11:02:11.580 に答える
0

productId 列が一意の ID であると仮定します。

delete  p1
from    AllProducts p1
join    AllProducts p2
on      p1.languageId = p2.languageId
and     p1.legislationId = p2.legislationId
and     p1.brandName = p2.brandName
and     p1.versionNumber = p2.versionNumber
and     p1.formulaId = p2.formulaId
and     p1.productId < p2.productId

これにより、一致する最新のレコードがすべて削除されます。

いくつかの基準 (たとえば、ブランド名とバージョン番号のみ) に一致するレコードを削除する場合は、結合から他の句を削除します。

于 2013-10-10T14:22:46.427 に答える
0

(productcode、languageid、legationid、brandName、versionnumber、formulaid order by productId desc によるパーティション) に対して row_number() を使用し、row_number > 1 のすべての producitids を削除できます。

于 2013-10-08T11:02:14.973 に答える