0

我有两个表“用户”和“关系”,我想选择所有用户的关系。

table relations
user1 user2
1     2
1     3
5     1

在上面的示例表中,它包含与用户表相关的 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);

我猜这接近我想要的。有人可以向我澄清我做错了什么吗?有没有更好的方法呢?

4

2 回答 2

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。

在这种情况下,存储的数据将更改为以下内容:

用户 1 用户 2
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这些查询的结果并确定哪个是最佳的。

于 2013-07-06T16:55:16.983 回答
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它将获取所有相关用户

这是你的小提琴

于 2013-07-06T16:55:48.383 回答