2009-04-09 6 views
1

일부 중복 항목이있는 테이블이 있습니다. 나는 하나를 제외한 모든 것을 버리고이 최신 것을 업데이트해야합니다. 나는 이런 식으로, 임시 테이블 잠시 문을 시도했다 :데이터베이스 대량 업데이트를 효율적으로 수행하려면 어떻게해야합니까?

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 Server에 특정한 경우 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의 대답은 사용 2005 + 구문, 그래서 내가 더 일반적인 것을 사용 가치가 내 하셨 지 2 펜스에 넣어 거라고 생각 SQL 서버 ...

첫째, "모든 중복 아닌 삭제하기 원본 "을 사용하려면 복제 레코드를 서로 구별하는 방법이 필요합니다. (Quassnoi의 대답 중 ROW_NUMBER() 부분)

소스 데이터에 ID 열 (사용자가 임시 테이블에 하나 생성)이없는 것처럼 보입니다. 그렇다면 두 가지 선택이 내 마음에 있습니다.
1. 데이터에 ID 열을 추가 한 다음 중복을 제거하십시오.
2. "중복 제거 된"데이터 세트를 만들고 모든 데이터를 삭제하십시오 원래, 원래

옵션 1로 다시 드 deduped 데이터를 삽입이 ... (새로 만든 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 
     ) 

또는이 될 수

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 큰있다 오버 헤드가 있지만 수백만 행을 업데이트/삭제하려는 경우 가장 빠른 방법입니다.

관련 문제