我有以下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,有没有办法扩展连接以显示这样的结果?
答案 0 :(得分:0)
以下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子句作为连接表的方法。
答案 1 :(得分:0)
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语法。
答案 2 :(得分:0)
要将用户的地址用作from和to名称的默认地址,您可以执行左连接并使用COALESCE
将空值替换为地址;
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
答案 3 :(得分:0)
我建议放弃"逗号"连接操作的语法;使用JOIN关键字,并将连接谓词移动到ON
子句而不是WHERE
子句。
要从orders
返回所有行,无论是否存在"匹配"从其他表中排,您可以使用外连接操作。
在SELECT列表中,您可以测试来自location
的{{1}}列是否为空,并在locations
表中返回address
列时,使用user
函数。
COALESCE
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
函数基本上是' CASE,当x IS为NULL,然后是EL END。
那里有一个角落案例,如果找到COALESCE(x,y)
表中的匹配行,但locations
列实际上包含NULL,该怎么办。
为了更准确地符合您的规范,您可以测试" location
"的值。在0
表的to_id
列中:
orders
但那里有一个角落案件;如果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值为" locations
"。
规范模式是通过检查找到匹配时保证为NOT NULL的列来测试是否从0
表返回行,如果匹配不是则为NULL实测值:
locations
所有这三个查询都会返回" normal"例;他们只是在角落情况和#34;处理完毕。
总结:
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
作为驱动表。