【问题标题】:Filtering elements in a table based on relation with same table根据与同一表的关系过滤表中的元素
【发布时间】:2019-10-25 02:32:08
【问题描述】:

我有一个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          |
+----+--------+------------+

【问题讨论】:

    标签: mysql database database-design query-optimization


    【解决方案1】:

    你可以使用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

    【讨论】:

    • 没有运气试图把它放在更大的查询中,have a look :)
    • @JeffWhite 请发布完整的 SQLFiddle 演示,以便我可以重现它
    • 你运气好吗?
    【解决方案2】:

    您可以使用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);
    

    如果跨部门关系也应该计算在内,也许您想删除平等部门的条件。

    【讨论】:

    • 伟大的开始,谢谢!只有一个小问题,设施表与另一个表(提供者)连接,当我运行它时,它会删除该设施的所有条目,所有提供者。我的完整查询如下:
    • SELECT ... FROM providers p JOIN providers_facilities_pivot pf ON p.id = pf.provider_id JOIN facility f ON pf.facility_id = f.id AND f.sector = 1 AND NOT EXISTS (SELECT * FROM设施 fs WHERE fs.sector = f.sector AND fs.located_in = f.id) ORDER BY p.id;
    • 供应商连接到多个设施。使用我的数据库中的数据,如果一个提供者具有我的 OP 中的确切设施(3 个,其中一个应该被删除),那么它会正确地从他那里删除它,但也从其他人那里删除,即使他们没有t 具有相同的安排 => 这意味着某些提供商可以仅连接到设施 ID 2 和 1,但由于另一个提供商,ID 2 仍会为他删除。
    • 我希望我写的东西有点清楚..有什么解决办法吗?
    • @JeffWhite:你应该发布一个新问题,并在那里充分披露完整的情况。
    【解决方案3】:

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

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

    【讨论】:

    • 嗨,乔恩,谢谢你的帮助!我问了这个问题,因为在我仍在努力解决的更大查询中需要它。这里的所有查询都遇到同样的问题,他们删除了列表中每个人的设施。也许你能找到问题? Here's what I'm talking about.
    猜你喜欢
    • 2018-07-14
    • 1970-01-01
    • 2015-10-26
    • 1970-01-01
    • 2019-10-22
    • 1970-01-01
    • 2022-06-11
    • 1970-01-01
    • 2021-12-29
    相关资源
    最近更新 更多