mysql选择两个字段中的一个,其中一个字段等于一个值

时间:2013-07-06 16:48:16

标签: mysql database relational-database

我有两个表“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);

这接近我想要的猜测。有人可以向我说清楚我做错了什么吗? 还有更好的方法吗?

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的约束,并且您有一个复合唯一键(user1user2) - 这很可能是你的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

或者像以下一样非常丑陋的查询,类似于您的尝试。这无疑会慢一点,我不推荐它(CASEOR是额外的处理步骤,会减慢速度,并可能使索引的使用无效):

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可以在user1user2中获取所有相关用户

HERE IS YOUR FIDDLE