我有一张表存放友谊关系。
它有列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']的值,但不能在左连接中使用它?
答案 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_id
在SELECT
中定义,因此不能在同一查询的其他位置使用。您必须使用子查询。一个简单的解决方案是将逻辑移到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);