I have a big SQL query (for MySQL) that is slow. It’s a union of two select statements. I have tried different things, but any slight variance gives me a different result set from the original. Any help with improving it will be greatly appreciated. Thanks. Here is the SQL:
(SELECT
CONCAT(city_name,', ',region) value,
latitude,
longitude,
id,
population,
( 3959 * acos( cos( radians($latitude) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians($longitude) ) + sin( radians($latitude) ) * sin( radians( latitude ) ) ) )
AS distance,
CASE region
WHEN '$region' THEN 1
ELSE 0
END AS region_match
FROM `cities`
$where and foo_count > 5
ORDER BY region_match desc, foo_count desc
limit 0, 11)
UNION
(SELECT
CONCAT(city_name,', ',region) value,
latitude,
longitude,
id,
population,
( 3959 * acos( cos( radians($latitude) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians($longitude) ) + sin( radians($latitude) ) * sin( radians( latitude ) ) ) )
AS distance,
CASE region
WHEN '$region' THEN 1
ELSE 0
END AS region_match
FROM `cities`
$where
ORDER BY region_match desc, population desc, distance asc
limit 0, 11)
limit 0, 11
The SQL does take some interpolated values (prefixed with the dollar sign($)).
The following might give the same result (I’m not sure about how the maximum/minimum functions are called in SQL, but you should get an idea — you need two fields derived from foo_count which separate the items of the first part of your UNION from those of the second one and allow ordering within the first part without disturbing the order in the second part) — of course, you later need a second query to throw the additional fields out again:
EDIT: Improvements