2016-08-26 5 views
1

У меня есть таблица с повторяющимися кодами, мне нужно очистить таблицу, удаляя повторяющуюся, но имеющую по крайней мере один слева от нее в таблице.Удалить повторяющиеся идентификаторы из таблицы - Улучшение производительности

Моя таблица такова:

FriendlyFunctionCode  MemberFirmId  FunctionLevel3Desc 
1       Value1   Value2 
1       Value2   Value3 
2       Value4   Value5 

мне нужно что-то вроде этого: (Это не имеет значения, какая строка остается, только, чтобы иметь по крайней мере один)

FriendlyFunctionCode  MemberFirmId  FunctionLevel3Desc 
1       Value1   Value2 
2       Value4   Value5 

У меня есть это запрос, но производительность ужасная

SELECT MemberFirmId, FriendlyFunctionCode 
INTO #ToDeleteRepeated 
FROM [dbo].[FirmFunction] 
GROUP BY MemberFirmId, FriendlyFunctionCode 
HAVING COUNT(1) > 1 

DECLARE @Code VARCHAR(100), @Desc VARCHAR(250) 

WHILE ((SELECT COUNT(1) FROM #ToDeleteRepeated) > 0) 
BEGIN 
    SELECT TOP 1 @Code = FriendlyFunctionCode FROM #ToDeleteRepeated 
    WHILE ((SELECT COUNT(1) FROM [FirmFunction] WHERE FriendlyFunctionCode = @Code) > 0) 
    BEGIN 
     SELECT TOP 1 @Desc = FunctionLevel3Desc FROM [FirmFunction] WHERE FriendlyFunctionCode = @Code 
     DELETE FROM [FirmFunction] WHERE FriendlyFunctionCode = @Code AND FunctionLevel3Desc = @Desc 
    END 
END 

Любые предложения?

+0

первым вы заботитесь, какая запись вы сохранить или удалить, если они имеют разные значения, относящиеся к FriendlyFunctionCode? Ваш запрос предполагает, что вы этого не делаете. Фактически, только для того, чтобы отметить, что ваш запрос будет удалять несколько записей, если FunctionLevel3Desc также повторяется. – Matt

ответ

3
WITH CTE AS (SELECT MemberFirmId, FriendlyFunctionCode, 
       ROW_NUMBER() over (PARTITION by FriendlyFunctionCode  ORDER BY FriendlyFunctionCode  ) AS RN 
       FROM [dbo].[FirmFunction] 
     ) 
     DELETE CTE WHERE CTE.RN >1 
+2

Я думаю, вам нужен раздел просто «FriendlyFunctionCode» –

+1

@Evaldas Buinauskas Я думаю, что вы правы, спасибо – Cato

+0

Удивительный ответ, попробовал и тоже работал как шарм. – Rednaxel

1

Вы можете использовать функцию окна, подобную этой. Сохраняет необходимость использования курсора (который плохо работает в SQL Server). Вы можете запустить внутренний select на своем, чтобы посмотреть, что он делает с номером строки.

Data Test

CREATE TABLE #TestData (FriendlyFunctionCode int, MemberFirmId nvarchar(10), FunctionLevel3Desc nvarchar(10)) 
INSERT INTO #TestData 
VALUES 
(1,'Value1','Value2') 
,(1,'Value2','Value3') 
,(2,'Value4','Value5') 

Запрос

SELECT 
a.FriendlyFunctionCode 
,a.MemberFirmId 
,a.FunctionLevel3Desc 
INTO #SavedData 
FROM 
(
    SELECT 
    FriendlyFunctionCode 
    ,MemberFirmId 
    ,FunctionLevel3Desc 
    ,ROW_NUMBER() OVER(PARTITION BY FriendlyFunctionCode ORDER BY FriendlyFunctionCode) RowNum 
    FROM #TestData 
) a 
WHERE a.RowNum = 1 

TRUNCATE TABLE #TestData 

INSERT INTO #TestData (FriendlyFunctionCode, MemberFirmId, FunctionLevel3Desc) 
SELECT 
FriendlyFunctionCode 
,MemberFirmId 
,FunctionLevel3Desc 
FROM #SavedData 

DROP TABLE #SavedData 

Результат

FriendlyFunctionCode MemberFirmId FunctionLevel3Desc 
1      Value1   Value2    
2      Value4   Value5     
+1

правая концепция, но фактически не удаляет запись – Matt

+1

Это справедливо. Я обновил свой ответ, чтобы обрезать исходную таблицу и вставить сохраненные записи. Выполнять лучше, чем удаление. –

0

Вы можете просто использовать MAX и группа по FunctionCode.

SELECT 
    FriendlyFunctionCode, 
    MAX(MemberFirmId) as MemberFirmId, 
    MAX(FunctionLevel3Desc) as FuncationLevel3Desc 
INTO #StagingTable 
FROM 
    FirmFunction 
GROUP BY 
    FriendlyFunctionCode 

Тогда Обрезать Ваш стол и выберите обратно в нее ... или просто создать таблицу все вместе и вставить отчетливую (макс) запись в него.

TRUNCATE TABLE FirmFunction 

INSERT INTO FirmFunction (FriendlyFunctionCode,MemberFirmId,FunctionLevel3Desc) 
SELECT * FROM #StagingTable 

Это менее безопасно, чем создание таблицы FirmFunction2, например с той же схеме, что и оригинал, а затем просто вставить в него, а затем переименовать его ....

SELECT TOP 1 INTO FirmFunction2 FROM FirmFunction WHERE 1=0 

INSERT INTO FirmFunction2 (FriendlyFunctionCode, MemberFirmId, FunctionLevel3Desc) 
SELECT 
     FriendlyFunctionCode, 
     MAX(MemberFirmId) as MemberFirmId, 
     MAX(FunctionLevel3Desc) as FuncationLevel3Desc 
    INTO #StagingTable 
    FROM 
     FirmFunction 
    GROUP BY 
     FriendlyFunctionCode 

Затем вы можете проверить дату в FirmFunction2, и если вы удовлетворены ... переименуйте ее после удаления другой таблицы.

+0

Хороший подход, он работает и работает как шарм. Спасибо. – Rednaxel

+1

@Rednaxel Я просто хочу подчеркнуть, что CTE великолепны, но используйте с особой осторожностью. Часто начинающие (не говорящие о том, что вы новичок) используют их как временные таблицы, в которых временные таблицы не могут использоваться. В этом нет ничего плохого, за исключением того, что CTE могут влиять на исходный источник данных, как вы намеренно делаете в своей ситуации. Таким образом, если вы выполняете и вставляете, удаляете и т. Д., Используя CTE, возврат невозможен. Убедитесь, что синтаксис правильный ... вы упорядочиваете и упорядочиваете правильно и т. Д. Метод, который я предоставил, не настолько оптимизирован, но менее подвержен ошибкам. – scsimon

+0

Спасибо за ваши комментарии, я буду осторожен с CTE. – Rednaxel

2

Удалить с помощью КТР с row_number()

;with cte as (
select *, row_number() over(partition by friendlyfunctioncode order by memberfirmid) rn 
from deletingtable) 
delete from cte where rn > 1 

Это выполняется с ниже плана выполнения:

Таблица/кластерный индекс сканирования -> сортировки (если нет индекса) -> сегмент -> Последовательность Project -> Фильтр, а затем удалить,

Если он имеет надлежащий индекс на FriendlyFunctionCode она выполняется быстрее в одном сканировании

+0

Как насчет возможных дополнительных указателей на таблице? –

+0

Не удаляйте повторно. – Rednaxel

+0

Значит, если есть больше индексов, то эти индексы будут иметь накладные расходы из-за удаления –