根据与同一表的关系过滤表中的元素

时间:2019-06-10 17:07:14

标签: mysql database database-design query-optimization

我有一个facilities表。列为id(主要),sector(整数)和located_in(可为空,引用在同一表上的id)。

在大多数情况下,located_in列为NULL,但是在某些情况下,facilities可以位于其他facilities内部。

在这种情况下,我希望父机构不成为结果的一部分(已删除)。

一个设施只能位于另一个设施中,而另一个设施也不能位于另一个设施中,因此不会深入到 n 级别。

数据集(View on SQLFiddle):

+----+--------+------------+
| ID | sector | located_in |
+----+--------+------------+
|  1 |      2 | NULL       |
|  2 |      2 | NULL       |
|  3 |      4 | NULL       |
|  4 |      1 | NULL       |
|  5 |      5 | NULL       |
|  6 |      2 | 2          |
+----+--------+------------+

查询(View on SQLFiddle):

SELECT * FROM facilities WHERE sector = 2;

预期结果(View on SQLFiddle):

+----+--------+------------+
| ID | sector | located_in |
+----+--------+------------+
|  1 |      2 | NULL       |
|  6 |      2 | 2          |
+----+--------+------------+

实际结果(View on SQLFiddle):

+----+--------+------------+
| ID | sector | located_in |
+----+--------+------------+
|  1 |      2 | NULL       |
|  2 |      2 | NULL       |
|  6 |      2 | 2          |
+----+--------+------------+

3 个答案:

答案 0 :(得分:0)

您可以使用LEFT JOIN

SELECT DISTINCT f.* 
FROM facilities f
LEFT JOIN facilities f2
  ON f.id = f2.located_in
WHERE f.sector = 2
  AND f2.ID IS NULL;

db<>fiddle demo

答案 1 :(得分:0)

您可以使用NOT EXISTS和相关的子查询来检查位置的任何子项。

SELECT *
       FROM facilities f1
       WHERE f1.sector = 2
             AND NOT EXISTS (SELECT *
                                    FROM facilities  f2
                                    WHERE f2.sector = f1.sector
                                          AND f2.located_in = f1.id);

如果跨部门关系也应考虑在内,也许您想删除相等部门上的条件。

答案 2 :(得分:0)

这是一个半差异。我首选的SQL公式:

select *
from facilities
where sector = 2
  and id not in (select located_in from facilities where located_in is not null);