MySQL从表中删除依赖于的行

时间:2015-07-17 01:52:37

标签: mysql delete-row

我正在尝试从我提供place_id的map_points表中删除行,但只有在place_id不是为同一map_id输入的另一个place_id的祖先时才删除

CREATE TABLE map_points {
    map_id int,
    place_id int
}

CREATE TABLE place_relation {
    ancestor int,
    child int
}


| map_id | place_id |
+--------+----------+
|   10   |    20    |
|   10   |    22    |
|   12   |    20    |
|   12   |    31    |
|   12   |    21    |
|   13   |    20    |
|   13   |    44    |
|   14   |    33    |
|   14   |    31    |
|   14   |    20    |
|   14   |    44    |
+--------+----------+


| ancestor | child |
+----------+-------+
|   20     |   22  |
|   20     |   21  |
|   31     |   33  |
+----------+-------+

我想删除place_id = 20的map_points,但是如果该地方在place_relation表中有子节点则不会。执行删除后,结果集应如下所示。

| map_id | place_id |
+--------+----------+
|   10   |    20    |
|   10   |    22    |
|   12   |    20    |
|   12   |    31    |<- deleted
|   12   |    21    |
|   13   |    20    |<- deleted
|   13   |    44    |
|   14   |    33    |
|   14   |    31    |
|   14   |    20    |<- deleted
|   14   |    44    |
+--------+----------+

这是我所处的位置,但它删除了太多记录

DELETE p
FROM map_points p
    JOIN place_relation r ON r.ancestor = p.place_id
    LEFT JOIN map_points p2 ON p2.map_id = p.map_id AND p2.place_id = r.child
WHERE p.place_id IN ( 20, 31 )
AND p2.place_id IS NULL

修改

我已从LEFT JOIN中删除了其中一个条件,但现在没有删除任何内容

DELETE p
FROM map_points p
    JOIN place_relation r ON r.ancestor = p.place_id
    LEFT JOIN map_points p2 ON p2.place_id = r.child
WHERE p.place_id IN ( 20, 31 )
AND p2.place_id IS NULL

修改

根据原始标准,以下查询会给出正确的结果

DELETE p
FROM map_points p
    JOIN place_relation r ON r.ancestor = p.place_id
    LEFT JOIN map_points p2 ON p2.map_id = p.map_id AND p2.place_id IN (
        SELECT child
        FROM place_relation 
        WHERE r.ancestor = ancestor 
    )
WHERE p.place_id IN ( 20, 31 )
AND p2.place_id IS NULL

已更新

在处理查询时,我通过添加更准确地反映活动数据库中数据的行来更新place_relation表。

| ancestor | child |
+----------+-------+
|    20    |   22  |
|    20    |   21  |
|    21    |   22  |*
|    31    |   33  |
+----------+-------+

期望的最终结果

| map_id | place_id |
+--------+----------+
|   10   |    20    |
|   10   |    21    |* // all ancestors are added to map_points table
|   10   |    22    |
|   12   |    20    |<- deleted
|   12   |    31    |<- deleted
|   12   |    21    |<- deleted
|   13   |    20    |<- deleted
|   13   |    44    |
|   14   |    33    |
|   14   |    31    |
|   14   |    20    |<- deleted
|   14   |    44    |
+--------+----------+

然后在WHERE标准中添加21     ...     在哪里p.place_id IN(20,21,31)

生成的DELETE没有从map_points表中删除行(12,20)。

因此,看起来这个查询只能在WHERE标准中取一个值。因此,在删除语句一次执行一个值之前,需要对数据进行排序。

有没有办法编写查询,以便可以在WHERE标准中输入多个值?

已更新

要获得具有多个值的所需结果,似乎我必须在子选择中输入多个值

DELETE p
FROM map_points p
    JOIN place_relation r ON r.ancestor = p.place_id
    LEFT JOIN map_points p2 ON p2.map_id = p.map_id AND p2.place_id IN (
        SELECT child
        FROM place_relation 
        WHERE r.ancestor = ancestor 
        AND child NOT IN (20,21,31)
    )
WHERE p.place_id IN (20,21,31)
AND p2.place_id IS NULL

1 个答案:

答案 0 :(得分:0)

-moz-user-select: none;中有太多条件:

left join

基本上,您的条件限制性太强,因此DELETE p FROM map_points p JOIN place_relation r ON r.ancestor = p.place_id LEFT JOIN map_points p2 ON p2.place_id = r.child WHERE p.place_id IN ( 20, 31 ) AND p2.place_id IS NULL; 中的记录无法匹配。因此,最终条件p2通常是正确的 - 并且将删除太多记录。