鉴于您的结构,一种方法是:
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
或者像下面这样非常丑陋的查询,类似于您的尝试。这无疑会更慢,我不推荐它(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
这些查询的结果并确定哪个是最佳的。