问题
I have an extremely ugly complex query that returns results for a race based on a series of groupings.
I have a table that contains registration information (name, etc), and a table that contains finish times. I need to get a place for each race, class, and division (they are sub groups of each other).
What I have working right now is this:
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';
So I am collecting all the competitors that are finished, and counting them where they are in the same race and same div, and their finish time is < the finish time of this record.
I now have a situation where I need the calculated race finish place to be displayed as the class finish place.. so I need to either duplicate the race position subquery in an if statement (uglier and slow), or move the subqueries to the where clause so I can use them more than once.
How would I reformat this query from a "count() from subquery where" single value subquery in the select to a join?
Is there some what I can reuse the inner subquery? if in add the class to it, I could count from it for every place counting.
Cheers,
回答1:
I know this won't help your code look any cleaner, but performance wise if you simply re-use the same subquery it will likely be cached so there shouldn't be a performance hit (generally as long as it doesn't use session variables or is a correlated subquery).
See what EXPLAIN EXTENDED
says and provided it doesn't come back with DEPENDENT SUBQUERY
or UNREACHABLE SUBQUERY
there shouldn't be a performance hit.
SELECT
*
FROM
(SELECT a FROM a) b INNER JOIN
(SELECT a FROM a) c ON b.a = c.a
The query optimizer should cache the subquery so that it is not actually retrieved twice.
来源:https://stackoverflow.com/questions/16878631/how-to-refactor-select-subqueries-into-joins