使用另一个字段的值作为左连接的默认值

时间:2014-03-26 19:10:58

标签: mysql sql left-join default-value

我有以下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,有没有办法扩展连接以显示这样的结果?

4 个答案:

答案 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

An SQLfiddle to test with

答案 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作为驱动表。
  • 在SELECT列表中使用条件表达式来确定要返回的列值