2013-10-28 80 views
1

我有兩個表:
如何保留外鍵在另一個表中的行並刪除其他重複的行?

A: 
id code 
1  A1 
2  A1 
3  B1 
4  B1 
5  C1 
6  C1 

=====================

B: 
id Aid 
1  1 
2  4 

B不含Aid其鏈接到code C1

讓我解釋一下整個流程:
我想讓每一行table A有不同的代碼(通過刪除重複的),和我はnt保留Aid,我可以在table B找到。如果Aid不保存在table B,我保留id更大一個。

,所以我不能只是做一些事情如下:

DELETE FROM A 
WHERE id NOT IN (SELECT MAX(id) 
        FROM A 
        GROUP BY code, 
) 

我可以通過下面的SQL語句獲取每個duplicate_code_groups:

SELECT code 
FROM A 
GROUP BY code 
HAVING COUNT(*) > 1 

有SQL中的一些代碼,就像

for (var ids in duplicate_code_groups){ 
    for (var id in ids) { 
     if (id in B){ 
      return id 
     } 
    } 

    return max(ids) 
} 

並將返回ID置入idtable ??我只是不知道如何在sql中編寫這樣的代碼。

然後我可以做

DELETE FROM A 
WHERE id NOT IN idtable 
+1

您的編輯更改了要求。首先,您想從A中刪除具有重複代碼的所有行(除了具有最高ID的行),現在您還想從A刪除所有行,並且只會出現一次代碼。你知道這個改變的要求嗎? –

+0

另外:如果您的第一個DELETE語句是您想要執行的語句(但排除外鍵約束禁止刪除的行),那麼您的問題的其餘部分只是模糊處理(因爲它與第一個DELETE語句衝突)。 –

+0

@Werner Henze讓我解釋一下總體流程:我想讓'table A'中的每一行都有不同的'code',並且我想保留'table B'中可以找到的'Aid'.If'Aid '不能保存在'表B'中,我保留這個id大一個。 – Mithril

回答

1

使用ROW_NUMBER()內CTE(或子查詢),你可以爲每個Code根據您的訂購指定的編號,然後就加入將結果集與您的表A進行刪除。

WITH CTE AS 
(
    SELECT A.*, ROW_NUMBER() OVER (PARTITION BY A.Code ORDER BY COALESCE(B.ID,0) DESC, A.ID desc) RN 
    FROM A 
    LEFT JOIN B ON A.ID = B.Aid 
) 
DELETE A FROM A 
INNER JOIN CTE C ON A.ID = C.ID 
WHERE RN > 1; 

SELECT * FROM A; 

SQLFiddle DEMO

0

嘗試這種解決方案

DELETE FROM A 
    WHERE NOT id IN 
    (
    SELECT MAX(B.AId) 
    FROM A INNER JOIN B ON A.id = B.aId 
    ) 
+0

這條語句將刪除'Aid',它不保存在'table:B'中 – Mithril

1

的第一選擇給你所有A.id是B中 - 你不想刪除它們。第二個選擇需要A,選擇所有沒有出現在B中的ID的代碼,並從這個子集取最大的id。這兩組ID是你想要保留的,所以刪除刪除不在組中的那些。

DELETE from A where A.id not in 
(
    select aid from B 
    union 
    select MAX(A.id) from A left outer join B on B.Aid=A.id group by code having COUNT(B.id)=0 
) 

MS SQL Server 2008 R2上的實際執行計劃顯示此解決方案表現相當好,比Nenad解決方案快5-6倍:)。

相關問題