从 tables 中选择匹配行与来自 table 匹配条件的值连接
Selecting matching rows from tables in join with values from either table matching a condition
场景
三个表:
- 订单
- 客户
- delivery_addresses
关系
- orders.customerId 指向 customers.id
- 订单.customerId指向delivery_addresses.customerId
目标
是 select orders 中满足 either 列条件的任何项目客户 或delivery_addresses。在更实际的意义上:我想搜索存储在 either customers 中的具有特定名称(或邮政编码或其他)的客户订单delivery_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.[= 中只有一个条目,我就不会得到结果13=]
因此,如果我像这样缩短查询:
SELECT orders.* FROM orders INNER JOIN customers ON orders.customerId = customers.id WHERE (customers.first_name LIKE "%max%")
我确实得到了正确的结果。
结论
我确信我遗漏了关于我对联接如何工作的理解的关键点。但是我不知道它是什么。
这里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%
您可以使用 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.*
....................
场景
三个表:
- 订单
- 客户
- delivery_addresses
关系
- orders.customerId 指向 customers.id
- 订单.customerId指向delivery_addresses.customerId
目标
是 select orders 中满足 either 列条件的任何项目客户 或delivery_addresses。在更实际的意义上:我想搜索存储在 either customers 中的具有特定名称(或邮政编码或其他)的客户订单delivery_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.[= 中只有一个条目,我就不会得到结果13=]
因此,如果我像这样缩短查询:
SELECT orders.* FROM orders INNER JOIN customers ON orders.customerId = customers.id WHERE (customers.first_name LIKE "%max%")
我确实得到了正确的结果。
结论
我确信我遗漏了关于我对联接如何工作的理解的关键点。但是我不知道它是什么。
这里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%
您可以使用 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.*
....................