mysql - 使用SQL执行唯一删除

标签 mysql sql sql-server sql-delete

我在 MySQL 中有几个这样的表:

A ---- A_has_B ---- B
    (many to many)  |
                    |
C ---- C_has_B-------
    (many to many)

鉴于以下情况,我需要从 B 中删除行:

  • 要删除的行在 C_has_B 中由 C.C_ID 引用
    • 要删除的行未被 C_has_B 中的其他 C.C_ID 引用
    • 要删除的行在A_has_B中也没有被引用

我能够使用以下方法获取 C.ID 引用的所有要删除的行:

DELETE * FROM C
JOIN C_has_B
ON(C.C_ID = C_has_B.C_ID)
JOIN B
on(C_has_B.B_ID = B.B_ID)
where C.C_ID = 1;

我不太确定如何实现最后两个条件。甚至可以只用 1 个查询来做到这一点吗?

最佳答案

您想从 B 中删除仅在 C_has_B 中引用一次且未被 A_has_B 引用的行。

使用子查询:

DELETE B
FROM
    B
JOIN
    (
       -- get rows from C_has_B that reference B_ID only once
       SELECT B_ID, Count(*)
       FROM C_has_B
       GROUP BY B_ID
       HAVING Count(*) = 1
    )
    as C_has_B_once
    on (B.B_ID = C_has_B_once.B_ID)
WHERE
    -- filter to rows not referenced by A_has_B
    B.B_ID not in (
       SELECT B_ID
       FROM A_has_B
    )

没有子查询:

DELETE B
FROM
    B
-- get rows from C_has_B that reference B_ID only once
-- (find 1 match via C_has_B1 and make sure there are no other C_IDs referencing the same B_ID via C_has_B2)
JOIN
    C_has_B as C_has_B1
    on (B.B_ID = C_has_B1.B_ID) and (A_has_B.B_ID = NULL)
LEFT JOIN
    C_has_B as C_has_B2
    on (C_has_B1.B_ID = C_has_B2.B_ID) and (C_has_B1.C_ID <> C_has_B2.C_ID)
-- filter to rows not referenced by A_has_B
LEFT JOIN
    A_has_B
    on (B.B_ID = A_has_B.B_ID) and (A_has_B.B_ID = NULL)
WHERE
    -- exclude rows that join to C_has_B2
    (C_has_B2.C_ID is NULL)

关于mysql - 使用SQL执行唯一删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6868483/

相关文章:

sql - 相关子查询出错。 "MultiPart ID oh.SalesOrderID could not be bound"

batch-file - mysqldump 批处理脚本以输出单个表以进行选择性还原

mysql - sql语句统计记录失败

mysql - 使用sql按组计算百分比

sql-server - 如何在数据流任务SSIS 2008 r2中传递变量

mysql - 在 Jasper 报告变量中使用 SUM

mysql - 导入数据 MySQL

mysql - SQL ExecuteScalar 2 返回值?

mysql - 在 MySQL 中存储多语言地理数据

MySQL:在选择算法中使用别名 - 未知字段