在LEFT JOIN中使用别名

时间:2017-01-08 13:06:00

标签: mysql

我有一张表存放友谊关系。

它有列id,userA和userB(userA的id总是小于userB的id)。

我尝试选择特定用户的所有友谊关系:

SELECT CASE friendships.userA WHEN (?) THEN friendships.userB ELSE friendships.userA END AS friend_id, users.username FROM friendships
LEFT JOIN users ON friend_id=users.id WHERE userA = (?) OR userB = (?) ORDER BY timestamp DESC LIMIT ? OFFSET ?;

$stmt->bind_param("iiiii",  $user_id, user_id, $user_id, $requestsPerLoad_db, $offset);

我收到以下错误消息:

  

'on clause'

中的未知列'friend_id'

这句话有什么问题?我可以获得$ row ['friend_id']的值,但不能在左连接中使用它?

3 个答案:

答案 0 :(得分:1)

这是您的查询:

SELECT (CASE f.userA WHEN (?) THEN f.userB ELSE f.userA END) AS friend_id,
       u.username
FROM friendships f LEFT JOIN
     users u
     ON friend_id = u.id
WHERE f.userA = (?) OR f.userB = (?)
ORDER BY timestamp DESC
LIMIT ? OFFSET ?;

friend_idSELECT中定义,因此不能在同一查询的其他位置使用。您必须使用子查询。一个简单的解决方案是将逻辑移到ON子句。这是一种方法:

ON (u.id = f.userA and f.userB = ?) or
   (u.id = f.userB and f.userA = ?)

另一种方法是完全跳过LEFT JOIN并将逻辑移到WHERE子句:

SELECT u.id, u.username
FROM users u
WHERE EXISTS (SELECT 1 
              FROM friendships f
              WHERE f.userB = ? AND f.userA = u.id
             ) OR
      EXISTS (SELECT 1
              FROM friendships f
              WHERE f.userA = ? AND f.userB = u.id
             ) 
ORDER BY timestamp DESC
LIMIT ? OFFSET ?;

这种方法的优点是查询可能能够利用适当的索引。

答案 1 :(得分:0)

那是因为它是派生列(或别名),而不是友谊table的一部分。您不能在列中存在两个表,而这两个表中的任何一个都不存在。

获取所有朋友的另一种方法是使用UNION查询,如下所示(我不确定为什么需要join,因为该列仅存在于friendships表中):

SELECT userB
FROM friendships
WHERE userA = ?

UNION

SELECT userA
FROM friendships
WHERE userB = ?

答案 2 :(得分:0)

我在ON语句中添加了CASE语句,它可以工作:

SELECT CASE friendships.userA WHEN (?) THEN friendships.userB ELSE friendships.userA END AS friend_id, users.username FROM friendships
LEFT JOIN users ON CASE friendships.userA WHEN (?) THEN friendships.userB ELSE friendships.userA END =users.id WHERE userA = (?) OR userB = (?) ORDER BY timestamp DESC LIMIT ? OFFSET ?;

$stmt->bind_param("iiiiii", $user_id, $user_id, $user_id, $user_id, $requestsPerLoad_db, $offset);