Sql 大查询和子查询的问题

Sql 大查询和子查询的问题,sql,mysql,Sql,Mysql,我想我会很聪明,使用子查询一次性获得我的数据。但在遇到问题并阅读文档后,我发现我的方法在MySQL中不起作用。我的内部查询返回约100条记录,外部查询扫描20000条记录。 当我将外部查询限制为20条记录时,它会运行20秒——非常慢 我想知道是否有可能以某种方式重新构造它,使内部查询不会每次都对外部查询中的每个记录运行 select p1.surname ,p1.name,p1.id,r1.start_date,r1.end_date,c1.short_name FROM ejl_players

我想我会很聪明,使用子查询一次性获得我的数据。但在遇到问题并阅读文档后,我发现我的方法在MySQL中不起作用。我的内部查询返回约100条记录,外部查询扫描20000条记录。 当我将外部查询限制为20条记录时,它会运行20秒——非常慢

我想知道是否有可能以某种方式重新构造它,使内部查询不会每次都对外部查询中的每个记录运行

select p1.surname ,p1.name,p1.id,r1.start_date,r1.end_date,c1.short_name
FROM ejl_players p1
left JOIN ejl_registration r1 ON ( r1.player_id = p1.id )
left JOIN ejl_teams t1 ON ( r1.team_id = t1.id )
left JOIN ejl_clubs c1 ON ( t1.club_id = c1.id )
where  r1.season=2008
and p1.id in
 (
SELECT p.id
FROM ejl_players p 
left JOIN ejl_registration r ON (r.player_id = p.id) 
left JOIN ejl_teams t ON (r.team_id = t.id) 
left JOIN ejl_clubs c ON (t.club_id = c.id)
WHERE r.season = 2008
GROUP BY p.id
HAVING COUNT(DISTINCT c.id)  > 1
)
解释(I)将外部查询限制为最多20条记录:

id  select_type  table  type  possible_keys  key  key_len  ref  rows  Extra  
1 PRIMARY p1 range PRIMARY PRIMARY 4 NULL 19 Using where 
1 PRIMARY r1 ref team_id,season season 10 const,d17528sd14898.p1.id 1 Using where 
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 d17528sd14898.r1.team_id 1   
1 PRIMARY c1 eq_ref PRIMARY PRIMARY 4 d17528sd14898.t1.club_id 1   
2 DEPENDENT SUBQUERY p index PRIMARY PRIMARY 5 NULL 23395 Using index 
2 DEPENDENT SUBQUERY r ref team_id,season season 10 const,d17528sd14898.p.id 1 Using where; Using index 
2 DEPENDENT SUBQUERY t eq_ref PRIMARY PRIMARY 4 d17528sd14898.r.team_id 1   
2 DEPENDENT SUBQUERY c eq_ref PRIMARY PRIMARY 4 d17528sd14898.t.club_id 1 Using index 
尝试使用内部联接(类似以下内容):

以这种方式使用子查询应该效率更高,但并不总是如此。但是,它确实绕过了为主查询中返回的每个记录执行子查询的问题。相反,子查询被构造为内存中的虚拟表,然后用于与主查询进行比较

编辑:我应该指出,您需要在MySQL中使用EXPLAIN来验证此查询是否确实执行得更有效。

尝试使用内部联接(类似于以下内容):

以这种方式使用子查询应该效率更高,但并不总是如此。但是,它确实绕过了为主查询中返回的每个记录执行子查询的问题。相反,子查询被构造为内存中的虚拟表,然后用于与主查询进行比较

编辑:我应该指出,您需要在MySQL中使用EXPLAIN来验证此查询是否确实执行得更有效。

就像我前几天在您的评论中所说的,在这个示例中,您不需要使用左连接。外部连接的执行速度通常比内部连接慢,因此您可以通过使用简单的内部jo来获得更好的性能在

只有当你需要显示所有玩家,甚至那些没有注册的玩家时,你才需要使用外部连接

您的查询似乎在寻找今年在多家俱乐部效力的球员(如您之前的问题),然后输出他们的注册和俱乐部名称的一些详细信息。以下是我将如何解决此查询:

SELECT p.surname, p.name, p.id, r.start_date, r.end_date, c1.short_name
FROM ejl_players p
 INNER JOIN ejl_registration r1 ON (r.player_id = p.id)
 INNER JOIN ejl_teams t1 ON (r.team_id = t1.id)
 INNER JOIN ejl_clubs c1 ON (t1.club_id = c1.id)
 INNER JOIN ejl_teams t2 ON (r.team_id = t2.id)
 INNER JOIN ejl_clubs c2 ON (t2.club_id = c2.id)
WHERE r.season = 2008
GROUP BY r.player_id, r.team_id
HAVING COUNT(DISTINCT c2.id) > 1;
这在MySQL中有效,因为MySQL允许使用单值规则。也就是说,GROUP BY子句中的列不必与select列表中命名的非聚合列相同。在其他品牌的RDBMS中,此查询将生成错误。

就像我前几天在您的日志中评论的那样,您不需要使用左J外部连接的执行速度通常比内部连接慢,因此使用简单的内部连接可以获得更好的性能

只有当你需要显示所有玩家,甚至那些没有注册的玩家时,你才需要使用外部连接

您的查询似乎在寻找今年在多家俱乐部效力的球员(如您之前的问题),然后输出他们的注册和俱乐部名称的一些详细信息。以下是我将如何解决此查询:

SELECT p.surname, p.name, p.id, r.start_date, r.end_date, c1.short_name
FROM ejl_players p
 INNER JOIN ejl_registration r1 ON (r.player_id = p.id)
 INNER JOIN ejl_teams t1 ON (r.team_id = t1.id)
 INNER JOIN ejl_clubs c1 ON (t1.club_id = c1.id)
 INNER JOIN ejl_teams t2 ON (r.team_id = t2.id)
 INNER JOIN ejl_clubs c2 ON (t2.club_id = c2.id)
WHERE r.season = 2008
GROUP BY r.player_id, r.team_id
HAVING COUNT(DISTINCT c2.id) > 1;

这在MySQL中起作用,因为MySQL允许使用单值规则。也就是说,GROUP BY子句中的列不必与select列表中命名的非聚合列相同。在其他品牌的RDBMS中,此查询将生成错误。

能否在查询中发布解释结果?请发布完整的CREATE当你问这样的问题时,表语句,这样我们就知道表之间声明的关系是什么。你能在查询中发布解释结果吗?当你问这样的问题时,请发布完整的CREATE TABLE语句,这样我们就知道表之间声明的关系是什么。IN是一种在几乎所有环境中都不好使用的构造以上的情况要好得多。在几乎所有情况下使用的构造都不好,上面的情况要好得多。比尔,我没有看你提到的原始问题。这些内部联接是否可能返回多于一行?如果是这样,那么你可能会在r.start\u date、r.end\u date或c1.short\u name上得到令人困惑的结果想一想,它们确实返回了多行。也就是说,一个人可以有多个注册。这不是问题。虽然这仅适用于个人,但团队-->俱乐部关系只能返回一行。我使用左连接来捕获可能的空值(某些团队没有俱乐部附加到它们)顺便说一句,您的查询返回0条记录。比尔,我没有看您引用的原始问题。这些内部联接是否可能返回多于一行?如果是这样,那么您可能会在r.start\u日期、r.end\u日期或c1.short\u名称上得到令人困惑的结果。我想关键是它们确实返回多行。也就是说,一个人可以多个注册。这不是问题。虽然这仅适用于个人团队,但团队-->俱乐部关系绑定仅返回一行。我使用左连接捕获可能的空值(某些团队没有俱乐部附加到它们),顺便说一句,您的查询返回0条记录。