2017-07-19 79 views
2

我有一張表,有長長的重複項目列表。我正在研究一個存儲過程,將它們整合到一個記錄中。每個重複項目都有一些子表格,這些子表格應該被刪除,或者重新生成以指向結果記錄。我的表有一個Id,但ReadableIdentifier是我需要重複刪除的列。刪除重複的行和依賴關係,無需光標

Id | ReadableIdentifier | Name  | UpdatedOn 
1 | ABC1234   | Product X | 2014-04-25 16:00:08.000 
2 | ABC1234   | Product X | 2014-04-28 16:00:08.000 
3 | ABC1234   | Product X | 2014-04-21 16:00:08.000 
4 | ABDD9945   | Widget R | 2014-04-25 16:00:08.000 
5 | ABDD9945   | Widget R | 2014-04-25 18:45:08.000 

正如你所看到的,記錄1-3是重複的,具有不同的Id和UpdatedOn日期。 4-5相同。我需要將這些記錄合併到一個記錄中,寧願使用最新UpdatedOn日期記錄。

最終目標(不顯示兒童表):

Id | ReadableIdentifier | Name  | UpdatedOn 
2 | ABC1234   | Product X | 2014-04-28 16:00:08.000 
5 | ABDD9945   | Widget R | 2014-04-25 18:45:08.000 

我使用的是CURSOR要做到這一點,但我不知道是否有更好的解決方案。

DECLARE dupeCursor CURSOR 
    FAST_FORWARD 
FOR 
    WITH Counts AS (
     SELECT 
      COUNT(1) Count, 
      ReadableIdentifier 
     FROM dbo.Item WITH (NOLOCK) 
     WHERE ReadableIdentifier IS NOT NULL 
     GROUP BY ReadableIdentifier) 
    SELECT 
     Counts.Count, 
     Counts.ReadableIdentifier, 
     Counts.CompanyId 
    FROM 
     Counts 
    WHERE Counts.Count > 1; 

OPEN dupeCursor; 
DECLARE @readableId VARCHAR(50); 
DECLARE @itemToPersistId INT, @itemToDeleteId INT; 
FETCH NEXT FROM dupeCursor INTO @readableId; 

WHILE @@FETCH_STATUS = 0 
BEGIN 

    WITH V AS (
     SELECT Id, ROW_NUMBER() OVER (PARTITION BY ReadableId ORDER BY UpdatedOn DESC) as Row 
     FROM dbo.Item WITH (NOLOCK) WHERE ReadableId = @readableId 
    ) 
    SELECT @itemToPersistId = Id 
    FROM V 
    WHERE V.Row = 1 

    CREATE TABLE #itemsToDelete (Id UNIQUEIDENTIFIER) 
    INSERT INTO #itemsToDelete 
    SELECT Id 
    FROM dbo.Item WITH (NOLOCK) 
    WHERE ReadableId = @readableId AND Id != @itemToPersistId; 

    --UPDATE CHILDREN TABLES 
    DELETE FROM dbo.ItemDetails WHERE ItemId IN (SELECT Id FROM #itemsToDelete); 

    UPDATE dbo.ItemPurchases SET ItemId = @itemToPersistId 
    WHERE ItemId IN (SELECT Id FROM #itemsToDelete); 

    UPDATE dbo.PurchaseOrders SET ItemId = @itemToPersistId 
    WHERE ItemId IN (SELECT Id FROM #itemsToDelete); 

    DELETE FROM dbo.ItemMetadata WHERE ItemId IN (SELECT Id FROM #itemsToDelete); 

    --delete Duplicated Items 
    DELETE FROM dbo.Item WHERE Id IN (SELECT Id FROM #itemsToDelete); 

    DROP TABLE #itemsToDelete 

    FETCH NEXT FROM dupeCursor INTO @readableId; 
END 

CLOSE dupeCursor; 
DEALLOCATE dupeCursor; 

我意識到光標很可能是問題,但我不知道如何去更新所有子表而不使用它。

回答

1

好吧我沒有數據來檢驗這個爲孩子表,但它應該工作:

WITH V 
    AS (SELECT *, 
       ROW_NUMBER() OVER(PARTITION BY ReadableId ORDER BY UpdatedOn DESC) AS Row 
     FROM dbo.Item WITH (NOLOCK)) 
    SELECT * 
    INTO #itemsToDelete 
    FROM V; 

--UPDATE CHILDREN TABLES 
DELETE FROM dbo.ItemDetails 
WHERE ItemId IN 
(
    SELECT Id 
    FROM #itemsToDelete 
    WHERE Row > 1 
); 
UPDATE IP 
    SET 
     IP.ItemId = itk.ID 
FROM dbo.ItemPurchases AS IP 
    INNER JOIN #itemsToDelete AS itd ON IP.ItemId = itd.ID 
             AND itd.Row > 1 
    INNER JOIN #itemsToDelete AS itk ON itk.ReadableIdentifier = itd.ReadableIdentifier 
             AND itk.Row = 1 
             AND itd.Row > 1; 
UPDATE po 
    SET 
     po.ItemId = itk.ID 
FROM dbo.PurchaseOrders AS po 
    INNER JOIN #itemsToDelete AS itd ON po.ItemId = itd.ID 
             AND itd.Row > 1 
    INNER JOIN #itemsToDelete AS itk ON itk.ReadableIdentifier = itd.ReadableIdentifier 
             AND itk.Row = 1 
             AND itd.Row > 1; 
DELETE FROM dbo.ItemMetadata 
WHERE ItemId IN 
(
    SELECT Id 
    FROM #itemsToDelete 
    WHERE Row > 1 
); 

--delete Duplicated Items 
DELETE FROM dbo.Item 
WHERE Id IN 
(
    SELECT Id 
    FROM #itemsToDelete 
    WHERE Row > 1 
); 
+0

權,我這個已經做了。如何在不使用CURSOR的情況下在子表上運行UPDATE/DELETE? – gwin003

+0

是其他表中的外鍵嗎? –

+0

是的,請參閱我的問題中的陳述。 – gwin003