【问题标题】:Selecting matching rows from tables in join with values from either table matching a condition从与条件匹配的任一表中的值连接的表中选择匹配的行
【发布时间】:2020-12-21 15:28:28
【问题描述】:

情景

三个表:

  • 订单
  • 客户
  • delivery_addresses

关系

  • orders.customerId 指向 customers.id
  • orders.customerId 指向 delivery_addresses.customerId

目标

是从 orders 中选择满足 customersdelivery_addresses 列条件的任何商品.在更实际的意义上:我想搜索存储在 either customersdelivery_addresses 中的具有特定名称(或邮政编码或其他)的客户订单强>。

我的尝试

我不太擅长连接及其背后的逻辑,但经过一些扎实的研究后,我想出了这个:

SELECT orders.* FROM orders INNER JOIN customers ON orders.customerId = customers.id INNER JOIN delivery_addresses ON orders.customerId = delivery_addresses.customerId WHERE ((customers.first_name LIKE "%max%") OR (delivery_addresses.first_name LIKE "%max%"))

但是,这不起作用。只有在 delivery_addresses 中有相应条目时,我才会得到结果,但如果 customers 中只有一个条目,则不会。

因此,如果我像这样缩短查询:

SELECT orders.* FROM orders INNER JOIN customers ON orders.customerId = customers.id WHERE (customers.first_name LIKE "%max%")

我确实得到了正确的结果。

结论

我确信我错过了一个关于我对连接如何工作的理解的关键点。但我不知道它是什么。

【问题讨论】:

  • 您可以使用Left/Right 加入。 Inner join 返回两个表上都存在的数据。
  • 感谢您的提示!但是由于我在语句中有两个连接,在给定的情况下应该是哪个?或者也许是一个完整的答案?
  • 你应该把它们都改成LEFT JOIN。像这样,您将返回来自customerdelivery_addresses 的所有订单和相关数据。这是第一个集合,之后,使用“WHERE”子句,您可以过滤符合您条件的退货订单的结果。
  • 知道了——谢谢!

标签: mysql join inner-join


【解决方案1】:

这里INNER JOIN 就像一个过滤器

SELECT orders.* 
FROM orders 
INNER JOIN customers ON orders.customerId = customers.id 
INNER JOIN delivery_addresses ON orders.customerId = delivery_addresses.customerId 
WHERE ((customers.first_name LIKE "%max%") 
  OR (delivery_addresses.first_name LIKE "%max%"))

可以使用LEFT JOIN重写:

SELECT orders.* 
FROM orders 
INNER JOIN customers ON orders.customerId = customers.id 
LEFT JOIN delivery_addresses ON orders.customerId = delivery_addresses.customerId 
WHERE customers.first_name LIKE '%max%'
   OR delivery_addresses.first_name LIKE'%max%
    

或者使用UNION:

SELECT orders.* 
FROM orders 
INNER JOIN customers ON orders.customerId = customers.id 
WHERE customers.first_name LIKE '%max%'
UNION
SELECT orders.* 
FROM orders 
INNER JOIN customers ON orders.customerId = customers.id 
INNER JOIN delivery_addresses ON orders.customerId = delivery_addresses.customerId 
WHERE delivery_addresses.first_name LIKE'%max%

【讨论】:

    【解决方案2】:

    您可以使用LEFT 连接和ON 子句中的所有条件来做到这一点:

    SELECT o.* 
    FROM orders o 
    LEFT JOIN customers c ON o.customerId = c.id AND c.first_name LIKE "%max%"
    LEFT JOIN delivery_addresses d ON o.customerId = d.customerId AND d.first_name LIKE "%max%"
    WHERE c.id IS NOT NULL OR d.customerId IS NOT NULL
    

    如果您得到重复的行,您可能需要在SELECT 之后添加DISTINCT

    SELECT DISTINCT o.*
    ....................
    

    【讨论】:

    • 如果我将条件放在 ON 子句中,这种情况有什么区别?
    • 如果你在 WHERE 子句中设置条件 c.first_name LIKE "%max%" 和 d.first_name LIKE "%max%" 那么你实际上是在做 INNER 连接所以你只会得到订单客户和交付地址中的 first_name 都匹配,这不是您想要的。在您的情况下,您至少需要 1 个匹配项。这就是为什么 WHERE 子句中唯一需要的条件是 c.id IS NOT NULL OR d.customerId IS NOT NULL
    • 我不知道为什么,但我实现了这一点并没有像所说的那样改变条件,而且效果很好,即使与三个或四个不同的表结合使用,即使诀窍是使用不同的表组合 WHERE 子句时的逻辑 (OR/AND)。但是谢谢你的帮助!所有 cmets 和帖子都非常有助于到达我需要去的地方。
    猜你喜欢
    • 1970-01-01
    • 2016-02-20
    • 1970-01-01
    • 1970-01-01
    • 2011-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多