MySQL 5.6。我有以下表格:
DESCRIBE profiles;
+----------------------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------------+---------------------+------+-----+---------+----------------+
| profile_id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| profile_given_name | varchar(100) | YES | MUL | NULL | |
| profile_surname | varchar(100) | YES | MUL | NULL | |
+----------------------------+---------------------+------+-----+---------+----------------+
describe friendships;
+----------------------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------+---------------------+------+-----+---------+----------------+
| friendship_id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| requester_profile_id | bigint(20) unsigned | NO | MUL | NULL | |
| recipient_profile_id | bigint(20) unsigned | NO | MUL | NULL | |
+----------------------+---------------------+------+-----+---------+----------------+
profiles
表表示系统的用户,friendships
表示用户与其他用户成为朋友的多对多关系。当用户/个人资料向用户发送“朋友请求”时,他们被认为是友情的requester
。相反,那些收到其他人的朋友请求的人是recipients
。
我正在尝试编写一个(看似简单的)符合ANSI标准的SELECT
,它告诉我特定个人资料所有的个人资料,无论他们是requester
还是{{ 1}}友谊。
使用某些数据设置数据库:
recipient
然后是我迄今为止最好的尝试:
INSERT INTO friendships (
friendship_ref_id,
requester_profile_id,
recipient_profile_id
) VALUES (
'01234',
2,
1
), (
'67890',
1,
3
), (
'78901',
1,
4
), (
'89012',
2,
3
), (
'90123',
3,
4
);
当我跑步时,我得到:
SELECT f.requester_profile_id,
f.recipient_profile_id
FROM profiles p
INNER JOIN friendships f
ON (
f.requester_profile_id = p.profile_id
OR
f.recipient_profile_id = p.profile_id
)
WHERE p.profile_id = 1;
但我真正想要的是由+----------------------+----------------------+
| requester_profile_id | recipient_profile_id |
+----------------------+----------------------+
| 1 | 2 |
| 1 | 3 |
| 1 | 4 |
| 2 | 1 |
+----------------------+----------------------+
所有DISTINCT
个人资料ID(请求者和收件人)组成的单个列,其中profile_id = 1
是朋友,例如:< / p>
+----------------------+
| profile_friends |
+----------------------+
| 2 |
| 3 |
| 4 |
+----------------------+
...由于profile_id = 1
是profile_id IN { 2, 3, 4 }
等朋友,
我在这里缺少什么来使查询有效?
答案 0 :(得分:1)
这里有两种选择。
第一个使用CASE来决定每个结果使用哪个列:
SELECT
CASE WHEN f.requester_profile_id = p.profile_id THEN f.recipient_profile_id
ELSE f.requester_profile_id END as profile_friends
FROM profiles p
INNER JOIN friendships f
/* Original ON clause would still work, but I prefer the briefer syntax */
ON p.profile_id IN (f.requester_profile_id,f.recipient_profile_id)
WHERE p.profile_id = 1;
第二个UNION将两个SELECT语句放在一起,其中一个检查请求者,另一个检查收件人:
SELECT f.recipient_profile_id as profile_friends
FROM profiles p
INNER JOIN friendships f
ON f.requester_profile_id = p.profile_id
WHERE p.profile_id = 1
UNION
SELECT f.requester_profile_id
FROM profiles p
INNER JOIN friendships f
ON f.recipient_profile_id = p.profile_id
WHERE p.profile_id = 1;
答案 1 :(得分:1)
我倾向于使用exists
执行此操作:
select p.*
from profiles p
where exists (select 1
from friendships f
where f.requester_profile_id = p.profile_id and
f.recipient_profile_id = 1
) or
(select 1
from friendships f
where f.recipient_profile_id = p.profile_id and
f.requester_profile_id = 1
);
此查询应包含两个索引:friendships(recipient_profile_id, requester_profile_id)
和friendships(requester_profile_id, recipient_profile_id)
。