Puoi provare qualcosa del genere (anche se per me non è pratico testarlo)
SELECT
sac.surveyId,
q.cat,
SUM((sac.answer_id*q.weight))/SUM(q.weight) AS score,
user.division_id,
user.unit_id,
user.department_id,
user.team_id,
division.division_name,
unit.unit_name,
dpt.department_name,
team.team_name
FROM survey_answers_cache sac
JOIN
(
SELECT
s.surveyId,
sc.subcluster_id
FROM
surveys s
JOIN subcluster sc ON s.subcluster_id = sc.subcluster_id
JOIN cluster c ON sc.cluster_id = c.cluster_id
WHERE
c.cluster_id=? AND sc.subcluster_id=? AND s.active=0 AND s.prepare=0
) AS v ON v.surveyid = sac.surveyid
JOIN user ON user.user_id = sac.user_id
JOIN questions q ON q.question_id = sac.question_id
JOIN division ON division.division_id = user.division_id
LEFT JOIN unit ON unit.unit_id = user.unit_id
LEFT JOIN department dpt ON dpt.department_id = user.department_id
LEFT JOIN team ON team.team_id = user.team_id
GROUP BY user.team_id, v.surveyId, q.cat
ORDER BY v.surveyId, user.team_id, q.cat ASC
Quindi spero di non aver sbagliato nulla.
Ad ogni modo, l'idea è che nella query interna selezioni solo le righe di cui hai bisogno in base alla tua condizione where. Questo creerà una tabella tmp più piccola poiché estrae solo 2 campi entrambi gli int.
Quindi nella query esterna ti unisci alle tabelle da cui estrai effettivamente il resto dei dati, ordina e raggruppa. In questo modo stai ordinando e raggruppando su un set di dati più piccolo. E la tua clausola where può essere eseguita nel modo più ottimale.
Potresti anche essere in grado di omettere alcune di queste tabelle come unico prelievo di dati da alcune di esse, ma senza vedere lo schema completo e come è correlato è difficile da dire.
Ma in generale questa parte (la sottoquery)
SELECT
s.surveyId,
sc.subcluster_id
FROM
surveys s
JOIN subcluster sc ON s.subcluster_id = sc.subcluster_id
JOIN cluster c ON sc.cluster_id = c.cluster_id
WHERE
c.cluster_id=? AND sc.subcluster_id=? AND s.active=0 AND s.prepare=0
È ciò che è direttamente influenzato dalla tua clausola WHERE. Vedi così possiamo ottimizzare questa parte, quindi usarla per unire il resto dei dati di cui hai bisogno.
Un esempio di rimozione delle tabelle può essere facilmente dedotto da quanto sopra, considera questo
SELECT
s.surveyId,
sc.subcluster_id
FROM
surveys s
JOIN subcluster sc ON s.subcluster_id = sc.subcluster_id
WHERE
sc.cluster_id=? AND sc.subcluster_id=? AND s.active=0 AND s.prepare=0
Il c
tabella cluster
non viene mai utilizzato per estrarre i dati da, solo per il dove. Così non è
JOIN cluster c ON sc.cluster_id = c.cluster_id
WHERE
c.cluster_id=?
Uguale o equivalente a
WHERE
sc.cluster_id=?
E quindi possiamo eliminare completamente quell'unione.