我有一张类似下面的表格:
id | Follower_id | leader_id | status
----------------------------------------
1 | 2 | 1 | approved
2 | 1 | 2 | approved
3 | 3 | 2 | approved
4 | 1 | 3 | approved
我要从此表中检索相互的Follower_id / leader_id。
对于示例2,此表中的1是相互的。为此,我使用以下sql
SELECT r.follower_id RF
, r.leader_id RL
, l.follower_id LF
, l.leader_id LL
FROM followers r
JOIN followers l
ON l.follower_id = r.leader_id
AND l.leader_id = r.follower_id
WHERE r.status = 'approved'
AND l.status = 'approved';
它返回预期的输出,但是非常慢。
如何优化此SQL?
答案 0 :(得分:0)
也许更简单的方法可能会更快地工作,例如
SELECT follower_id, leader_id
FROM followers a
WHERE follower_id IN (
SELECT follower_id
FROM followers b
WHERE a.leader_id = b.leader_id
AND status = 'approved'
)
AND status = 'approved';
答案 1 :(得分:0)
您正在将整个表与同一张表连接在一起。那没有道理。尝试“内部加入”,这样在领导者拥有相同追随者或跟随者具有相同领导者的情况下,您将获得收益。另外,您还需要使用as
别名来连接您的表。
SELECT *
FROM followers as f
INNER JOIN followers as k on f.follower_id = k.leader_id
WHERE f.follower_id like k.leader_id OR f.follower_id = k.leader_id
在有人大惊小怪之前,这是一个示例脚本,向您显示了bouth表的所有条目。在这种情况下,两次是同一张桌子。
更好的方法是制作2张桌子。创建一个记帐表和一个跟随表并将它们联接。应该也可以正常工作,而且速度更快。
如果您想使用更多方法连接表,请在这里查看:https://www.w3schools.com/sql/sql_join.asp
答案 2 :(得分:0)
您的查询产生重复的记录。这也会给您的mysql连接造成一些延迟。
避免重复就是解决您的问题。
我在下面添加我的作品,
SELECT r.follower_id RF
, r.leader_id RL
, l.follower_id LF
, l.leader_id LL
FROM sample r
JOIN sample l
ON l.follower_id = r.leader_id
AND l.leader_id = r.follower_id AND r.id < l.id
WHERE r.status = 'approved'
AND l.status = 'approved';
输出:
RF RL LF LL
2 1 1 2
注意:请使用table name
的{{1}}代言。
答案 3 :(得分:0)
有时候EXISTS非常有效:
select
t.follower_id id1,
t.leader_id id2
from followers t
where
status = 'approved'
and
t.follower_id < t.leader_id
and
exists (
select 1 from followers
where status = 'approved' and follower_id = t.leader_id and leader_id = t.follower_id
)
此查询将仅返回每对一次。
请参见demo。
结果:
| id1 | id2 |
| --- | --- |
| 1 | 2 |
答案 4 :(得分:0)
首先,您可以使用索引优化此查询:
SELECT r.follower_id as RF, r.leader_id as RL,
l.follower_id as LF, l.leader_id as LL
FROM followers r JOIN
followers l
ON l.follower_id = r.leader_id AND
l.leader_id = r.follower_id
WHERE r.status = 'approved' AND l.status = 'approved';
以下索引应该有帮助:followers(follower_id, leader_id, status)
。
我更愿意将其写为exists
。您也可以尝试聚合:
SELECT f.follower_id, f.leader_id
FROM followers f
WHERE f.status = 'approved'
GROUP BY LEAST(f.follower_id, f.leader_id),
GREATEST(f.follower_id, f.leader_id)
HAVING MIN(f.follower_id) = MIN(f.leader_id);
最后一个条件保证您在数据中有两个方向。