我有两个表“users”和“relations”,我想选择所有用户的关系。
table relations
user1 user2
1 2
1 3
5 1
在上面的示例表中,它保存了与users表相关的id。
我想为用户ID 1选择所有关系并加入他朋友的名字,例如,应该期待返回
id name
2 demo friends1
3 demo friends2
5 demo friends3
所以我尝试了: -
Select (case user1='1' then r.user2 else r.user1 end) as id,u.name from relations r
join users u on u.id = (case r.user1='1' then r.user2 else r.user1 end)
where (user1 = 1 or user2= 2);
这接近我想要的猜测。有人可以向我说清楚我做错了什么吗? 还有更好的方法吗?
答案 0 :(得分:0)
鉴于您的结构,一种方法是:
SELECT users.id, users.name
FROM relations
INNER JOIN users ON relations.user2 = users.id
WHERE relations.user1 = 1
UNION ALL
SELECT users.id, users.name
FROM relations
INNER JOIN users ON relations.user1 = users.id
WHERE relations.user2 = 1
这确实假设您正在努力不包含重复的行。确保这一点的一种方法是建立user1
应始终小于user2
的约束,并且您有一个复合唯一键(user1
,user2
) - 这很可能是你的PK。
在这种情况下,存储的数据将更改为以下内容:
user1 user2 1 2 1 3 1 5
为了完整理解,还有其他方法可以实现您的愿望。此查询几乎与第一个查询相同,只是联合是在派生表中而不是在最外层中。一个好的查询优化器可能会将两者识别为相同:
SELECT users.id, users.name
FROM users
INNER JOIN
(
SELECT user1 AS id FROM relations WHERE user2 = 1
UNION ALL
SELECT user2 AS id FROM relations WHERE user1 = 1
) friends ON users.id = friends.id
或者像以下一样非常丑陋的查询,类似于您的尝试。这无疑会慢一点,我不推荐它(CASE
和OR
是额外的处理步骤,会减慢速度,并可能使索引的使用无效):
SELECT users.id, users.name
FROM users
INNER JOIN
(
SELECT CASE WHEN user1 = 1 THEN user2 ELSE user1 END AS id
FROM relations
WHERE user1 = 1 OR user2 = 1
) friends ON users.id = friends.id
您可以查看这些查询的EXPLAIN
结果,并确定哪个最合适。
答案 1 :(得分:0)
你也可以这样做
SELECT * FROM `users` WHERE id IN (SELECT user1 FROM relations WHERE user2='1')
OR
id IN(SELECT user2 FROM relations WHERE user1='1')
id 1可以在user1
或user2
中获取所有相关用户