2013-10-08 2 views
0

В настоящее время я работаю над сценарием DataImport, который предназначен для перемещения данных из одной базы данных в другую. Основная проблема, с которой я столкнулся, заключается в том, что в рассматриваемой таблице много повторяющихся записей, причем дублирующиеся поля - это код продукта, язык, законодательство, фирменное наименование, формула и версия, то есть в базе данных могут быть следующие:SQL Server 2005 - удаление дубликатов записей при сохранении первого

My Test продукт, английский, Великобритания, тест Марк, тест Формула, 1 (ID 1 - не входит в группе)
My Test продукт, английский, Великобритания, тест Марк, тест Формула, 1 (ID 2 - не входит в группу)
Мой тестовый продукт, английский, Великобритания, тестовая марка, тестовая формула, 1 (ID 3 - не входит в группу)
Мой тестовый продукт, английский, Великобритания, тестовая марка, 1 (ID 4 - не входит в группу)

Как вы можете видеть, эти записи одинаковы во всех отношениях. Моя проблема заключается в том, что в качестве части сценария загрузки данных я хочу удалить записи с идентификаторами 1, 2 и 3, сохранив запись с идентификатором 4, поскольку это будет самая последняя запись, и, следовательно, одна Я хочу сохранить. Для этого я написал 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 

Теперь это делает работу - его просто невероятно медленно, и я не могу думать о какой-либо простой способ сделать это быстрее. Есть ли у кого-нибудь идеи, как я могу поддерживать ту же функциональность, но заставить ее работать быстрее?

+0

Возможный дубликат [Как удалить повторяющиеся строки?] (Http://stackoverflow.com/questions/18932/how-can-i-remove-duplicate-rows) –

ответ

3

Вы уже можете использовать common-table-expression и ROW_NUMBER в SQL_Server 2005:

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 *, если вы хотите увидеть, что вы будете удалять.

+0

Это отличное решение, спасибо! – Andrew

0

Вы можете использовать row_number() над (раздел по ProductCode, LanguageID, legislationid, брендовых, VersionNumber, formulaid заказ по ProductID DESC) и удалить все producitids с row_number> 1

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 

Это удалит все положенные последние записи, где есть совпадения.

Если вы хотите удалить записи, соответствующие определенным критериям (например, только фирменное наименование и номер версии, затем удалите другие предложения из объединения).

Смежные вопросы