如何将子查询重构为连接?

时间:2013-06-02 00:30:26

标签: mysql refactoring subquery

我有一个非常丑陋的复杂查询,它根据一系列分组返回竞赛结果。

我有一个包含注册信息(名称等)的表,以及一个包含完成时间的表。我需要为每个种族,阶级和分区获得一个位置(它们是彼此的子组)。

我现在正在做的是:

Select reg.name, r.fin_time
  ( select count(*)+1 from 
    ( Select temp_reg.id as regid, temp_reg.race_id as in_race, temp_res.division as in_div, 
         COALESCE(temp_res.fin_time, 9999999999) as finish_time 
      FROM results as temp_res Inner JOIN registration as temp_reg on temp_res.registration_id = temp_reg.id 
      WHERE COALESCE(temp_res.fin_time) > 0 
        AND temp_res.status ='Finished') as ahead_div 
    WHERE ahead_div.regid <> reg.registration_id 
      AND ahead_div.in_race = reg.race_id 
      AND ahead_div.in_div = r.division 
      AND ahead_div.finish_time < COALESCE(r.fin_time, 9999999999) ), '-') as fin_place_div,
... same for class and race...
FROM results as r inner join registration as reg on r.registration_id = reg.id 
WHERE r.status = 'Finished';

因此,我正在收集所有已完成的竞争对手,并计算他们在相同的比赛和相同的div中的位置,并且他们的完成时间是&lt;这张唱片的结束时间。

我现在有一种情况,我需要将计算出的比赛结束位置显示为类完成位置..所以我需要在if语句中复制比赛位置子查询(丑陋和慢),或者移动子查询到where子句,所以我可以多次使用它们。

如何从子查询中的“count()”重新格式化此查询,其中“select中的单值子查询到连接?

是否有一些我可以重用内部子查询的东西?如果将类加入其中,我可以从中计算每个地方的数量。

干杯,

1 个答案:

答案 0 :(得分:0)

我知道这不会帮助你的代码看起来更干净,但是如果你只是重复使用相同的子查询它可能会被缓存,因此不会有性能损失(通常只要它没有'使用会话变量或是相关的子查询)。

查看EXPLAIN EXTENDED所说的内容,如果DEPENDENT SUBQUERYUNREACHABLE SUBQUERY没有回复,则不应该有性能损失。

SELECT
   *
FROM
   (SELECT a FROM a) b INNER JOIN
   (SELECT a FROM a) c ON b.a = c.a

查询优化器应该缓存子查询,以便实际上不会检索两次。