【问题标题】:How to remove orphan rows in multiple left join in mysql?如何删除mysql中多个左连接中的孤立行?
【发布时间】:2013-12-20 14:34:01
【问题描述】:

我正在使用这个查询

SELECT * FROM parent_table
LEFT JOIN child_tab ON parent_table.id = child_tab.parent_id
LEFT JOIN child_tab2 ON parent_table.id =  child_tab2.parent_id 

如果我像这样添加这个条件:

WHERE child_tab2.parent_id IS NOT NULL
OR child_tab.parent_id IS NOT NULL;

之后,孤立行将被删除。如果连接条件超过两个三个表就可以了 但我不希望在WHERE 子句中实现这种类型,因为我的连接条件是动态的,并且没有子表是可变的。(最多可能是 1 到 20)

【问题讨论】:

  • Afaik 你在 where 子句中需要一些东西。使用 where 子句到底有什么问题?覆盖所有表格的单一条件是否可行?
  • 你能用一个例子来做一个小提琴吗?
  • 为什么可变数量的子表会成为问题?
  • 这是sqlite 还是mysql
  • 这个WHERE COALESCE(child_tab.parent_id, child_tab2.parent_id) IS NOT NULL 更短。请注意,COALESCE 至少需要 2 个参数。

标签: mysql oracle sqlite


【解决方案1】:

如果您的连接是可变的和动态的,您别无选择,只能在 WHERE 子句中进行过滤。但是,如果它感觉更优雅,您可以避免重复 OR OR OR 与此,这可以简化 where 子句的逻辑表达式:

WHERE COALESCE(child_tab.parent_id, child_tab2.parent_id) IS NOT NULL

COALESCE() 接受一个包含许多参数的列表——不仅仅是两个——并返回最左边的非空参数的值,如果它们都为空,则返回空。

http://dev.mysql.com/doc/refman/5.6/en/comparison-operators.html#function_coalesce

【讨论】:

    【解决方案2】:

    您的WHERE 毫无意义,因为LEFT JOIN 将忽略所有不匹配的(和NULL)子表ID。

    您可以使用以下内容:

    SELECT * FROM parent_table
    JOIN child_tab ON parent_table.id = child_tab.parent_id
    LEFT JOIN child_tab2 ON parent_table.id =  child_tab2.parent_id
    UNION
    SELECT * FROM parent_table
    LEFT JOIN child_tab ON parent_table.id = child_tab.parent_id
    JOIN child_tab2 ON parent_table.id =  child_tab2.parent_id;
    

    但我看不出比使用WHERE 子句有任何优势,如下所示:

    SELECT *
    FROM parent_table
         JOIN child_tab ON parent_table.id = child_tab.parent_id
    LEFT JOIN child_tab2 ON parent_table.id =  child_tab2.parent_id
    UNION
    SELECT *
    FROM parent_table
    LEFT JOIN child_tab ON parent_table.id = child_tab.parent_id
         JOIN child_tab2 ON parent_table.id =  child_tab2.parent_id;
    

    » SQL Fiddle sample

    【讨论】:

    • INNER JOIN 等价于 WHERE a IS NOT NOT AND b IS NOT NULL,OP 在这种情况下想要一个 OR
    【解决方案3】:

    我为这个问题创造了一个小提琴:SQLFiddle

    基本上,您需要左右连接以及UNION

    SELECT * 
      FROM parent_table
      JOIN (
             SELECT  
                    child_tab.parent_id as cparent_id, 
                    child_tab2.parent_id as c2parent_id
               FROM child_tab 
          LEFT JOIN child_tab2
                       ON child_tab.parent_id =  child_tab2.parent_id 
         UNION
             SELECT 
                    child_tab2.parent_id as cparent_id, 
                    child_tab.parent_id as c2parent_id
               FROM child_tab 
          RIGHT JOIN child_tab2
                       ON child_tab.parent_id =  child_tab2.parent_id 
           ) AS s1
        ON parent_table.id = s1.cparent_id
    

    【讨论】:

    • 不一定所有子表都有与父表相关的数据,例如一个表有四个父 ID 为“5”的记录,另一个表没有任何父 ID 为“5”的记录在内部连接的情况下,它将返回无,在左连接的情况下,它将返回与父 ID 5 相关的数据对于表一个和另一个表行将与相同的父 id “5”一起为空白
    猜你喜欢
    • 2015-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-20
    • 1970-01-01
    • 2016-07-08
    • 2019-05-30
    • 1970-01-01
    相关资源
    最近更新 更多