Given the following query, how can I optimize it so that the subqueries are not dependent?
SELECT DISTINCT
inst.id, inst.name, inst.state, inst.farm_status,
(SELECT COUNT(inst_note.id)
FROM project_institution_note AS inst_note
WHERE inst_note.institution_id = inst.id) AS inst_note_count,
(SELECT COUNT(c.id) FROM project_catalog AS c
WHERE c.institution_id = inst.id
AND c.status = 0
AND c.catalog_type BETWEEN 0 AND 1) AS ug_count,
(SELECT COUNT(c.id) FROM project_catalog AS c
WHERE c.institution_id = inst.id
AND c.status = 0
AND c.catalog_type BETWEEN 1 AND 2) AS grad_count,
(SELECT COUNT(c.id) FROM project_catalog AS c
WHERE c.institution_id = inst.id
AND c.status = 0 AND c.catalog_type >= 3) AS alt_count,
(SELECT COUNT(c.id) FROM project_catalog_note AS cn
INNER JOIN farmtool_catalog AS c
ON c.id = cn.catalog_id
WHERE c.institution_id = inst.id) AS catalog_note_count,
(SELECT inst_note.text FROM project_institution_note AS inst_note
LEFT JOIN project_institution AS inst
ON inst_note.institution_id = inst.id
WHERE inst_note.institution_id = inst.id
ORDER BY inst_note.date DESC
LIMIT 1) AS latest_note
FROM project_institution AS inst
LEFT JOIN project_institution_note AS inst_note
ON inst.id = inst_note.institution_id
LEFT JOIN project_catalog AS c
ON inst.id = c.institution_id
WHERE LOWER(inst.state) = "me";
I've tried refactoring the first subquery into an INNER JOIN
like so:
INNER JOIN (SELECT COUNT(inst_note.id)
FROM project_institution_note AS inst_note
GROUP BY inst_note.institution_id) inst_note_count
ON inst_note.institution_id = inst.id
and included it after the last LEFT JOIN
operation, but returned an empty result.
Of particular interest for me is optimizing the second and third subqueries that calcuate ug_count
and grad_count
. The only difference between the two is the first is dependent on a field value between (0, 1), and the second between (1, 2).
Right now, this query runs fine, and is in a low use scenario. Still, its obviously pretty inefficient, so I'd like to optimize if possible.