Mysql 使用另一个字段的值作为左联接的默认值
我有以下三个表格:Mysql 使用另一个字段的值作为左联接的默认值,mysql,sql,left-join,default-value,Mysql,Sql,Left Join,Default Value,我有以下三个表格: users | id | name | address | |----+-------+----------+ | 1 | user1 | address1 | | 2 | user2 | address2 | locations | id | user_id | name | |----+---------+-----------+ | 1 | 1 | location1 | | 2 | 1 | location2 | | 3
users
| id | name | address |
|----+-------+----------+
| 1 | user1 | address1 |
| 2 | user2 | address2 |
locations
| id | user_id | name |
|----+---------+-----------+
| 1 | 1 | location1 |
| 2 | 1 | location2 |
| 3 | 2 | location3 |
orders
| id | user_id | from_id | to_id |
|----+---------+---------+-------+
| 1 | 1 | 1 | 2 |
| 2 | 1 | 1 | 0 |
from_id或to_id可以有0,这意味着在本例中使用了用户的地址
在这些表上执行“朴素”联接:
SELECT u.name uname, fl.location flocation, tl.location tlocation
FROM users u, orders o, locations fl, locations tl
WHERE u.id = o.user_id
AND o.from_id = fl.id
AND o.to_id = tl.id
不显示包含0的记录:
user1 | location1 | location2
我想看到的是以下数据:
user1 | location1 | location2
user1 | location1 | address1
使用mysql,有没有办法扩展连接以显示这样的结果?以下SQL应该可以做到这一点:
SELECT u.name uname, IF(fl.id, fl.location, u.address) AS flocation, IF(tl.id, tl.location, u.address) AS tlocation
FROM users u
INNER JOIN orders o ON u.id = o.user_id
LEFT JOIN locations fl ON o.from_id = fl.id
LEFT JOIN locations tl ON o.to_id = tl.id;
如果我可以提出一个建议,我建议您不要使用WHERE子句作为连接表的方式
SELECT u.name uname, fl.location flocation, tl.location tlocation
FROM users u
left join orders o
on u.id = o.user_id
left join locations fl
on o.from_id = fl.id
left join locations tl
on o.to_id = tl.id
这将为您提供所有用户的数据
正如蒂姆·伯奇(Tim Burch)所建议的,最好使用ANSI SQL语法。要使用用户地址作为发件人和收件人名称的默认值,您可以进行左连接,并使用
合并
将空值替换为地址
SELECT
u.name uname,
COALESCE(fl.name, u.address) flocation,
COALESCE(tl.name, u.address) tlocation
FROM users u
JOIN orders o ON u.id = o.user_id
LEFT JOIN locations fl ON o.from_id = fl.id
LEFT JOIN locations tl ON o.to_id = tl.id
.我建议放弃join操作的“逗号”语法;使用JOIN关键字,将连接谓词移动到
ON
子句,而不是WHERE
子句
要从返回的订单中获取所有行,无论其他表中是否有“匹配”行,都可以使用外部联接操作
在选择列表中,您可以测试位置
中的位置
列是否为空,并使用合并
功能从用户
表返回地址
列
SELECT u.name uname
, COALESCE(fl.location,u.address) flocation
, COALESCE(tl.location,u.address) tlocation
FROM orders o
LEFT
JOIN users u
ON u.id = o.user_id
LEFT
JOIN locations fl
ON fl.id = o.from_id
LEFT
JOIN locations tl
ON tl.id = o.to_id
COALESCE(x,y)
函数本质上是“当x为NULL时,则y为x结束”的简写形式
这里有一个小例子,如果在locations
表中找到了匹配的行,但location
列实际上包含空值,该怎么办
为了更精确地匹配您的规范,您可以在订单
表的To\u id
列中测试值“0
:
SELECT u.name uname
, IF(o.from_id = 0, u.address, fl.location) flocation
, IF(o.to_id = 0, u.address, tl.location) tlocation
FROM orders o
LEFT
JOIN users u
ON u.id = o.user_id
LEFT
JOIN locations fl
ON fl.id = o.from_id
LEFT
JOIN locations tl
ON tl.id = o.to_id
但这里有一个角落的案例;如果位置中有一行id值为“0
”该怎么办
标准模式是通过检查一列来测试行是否从位置返回,该列在找到匹配项时保证不为空,在没有找到匹配项时保证为空:
SELECT u.name uname
, IF(fl.id IS NULL, u.address, fl.location) flocation
, IF(tl.id IS NULL, u.address, tl.location) tlocation
FROM orders o
LEFT
JOIN users u
ON u.id = o.user_id
LEFT
JOIN locations fl
ON fl.id = o.from_id
LEFT
JOIN locations tl
ON tl.id = o.to_id
对于“正常”情况,所有这三个查询将返回相同的结果;他们只是在处理“角落案件”的方式上有所不同
总之:
- 使用
LEFT[OUTER]JOIN
操作和orders
作为驱动表
- 使用“选择”列表中的条件表达式确定要返回的列值