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都有不同的代码(通过删除重复),我想保留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
4

3 回答 3

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 演示

于 2013-10-28T08:58:28.640 回答
1

第一个选择为您提供 B 中的所有 A.id - 您不想删除它们。第二个选择取 A,选择 B 中出现的所有没有 id 的代码,并从这个子集中取最大 id。这两组 id 是你要保留的,所以 delete 会删除那些不在集合中的。

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 倍:)。

于 2013-10-28T09:09:22.677 回答
0

试试这个解决方案

 DELETE FROM A
    WHERE NOT id IN
    (
    SELECT MAX(B.AId) 
    FROM A INNER JOIN B ON A.id = B.aId
    )
于 2013-10-28T08:30:19.280 回答