Tout d'abord, jetez un coup d'œil à votre plan d'exécution. Il est difficile pour nous de l'optimiser car nous ne connaissons pas vos données.
La chose qui saute le plus est la pièce wr.wr_wo_id IN (SELECT...)
. Ce serait beaucoup plus efficace comme une jointure, comme ceci:
SELECT wr.wr_re_id as ReID, sum(wr.wr_total) as PRTotal
FROM Workorder2 w
INNER JOIN Workorder_Row2 wr on wr.wr_wo_id = w.wo_id
INNER JOIN (
SELECT DISTINCT wr2.wr_wo_id
FROM Workorder_Row2 wr2
INNER JOIN Workorder2 w2 on w2.wo_id = wr2.wr_wo_id
WHERE w2.wo_date_time >= '2010-01-01'
AND w2.wo_date_time <= '2010-01-31'
AND wr2.wr_row_type = 1
) T ON T.wr_wo_id = wr.wr_wo_id
WHERE (w.wo_type = 1 or w.wo_type = 2)
AND wr.wr_row_type = 2
AND w.wo_lo_id like '%'
AND w.wo_date_time >= '2010-01-01' AND w.wo_date_time <= '2010-01-31'
GROUP BY wr.wr_re_id
Il est utile de considérer si cela aiderait à ajouter des indices. Cela dépend de la fréquence de mise à jour/insertion/suppression de ces tables et de la sélectivité de chaque colonne.
COMPLEMENTAIRES:
Pour faire l'inverse, à savoir remplacer WHERE wr.wr_wo_id NOT IN (SELECT...)
, vous utilisez:
SELECT wr.wr_re_id as ReID, sum(wr.wr_total) as PRTotal
FROM Workorder2 w
INNER JOIN Workorder_Row2 wr on wr.wr_wo_id = w.wo_id
LEFT JOIN (
SELECT DISTINCT wr2.wr_wo_id
FROM Workorder_Row2 wr2
INNER JOIN Workorder2 w2 on w2.wo_id = wr2.wr_wo_id
WHERE w2.wo_date_time >= '2010-01-01'
AND w2.wo_date_time <= '2010-01-31'
AND wr2.wr_row_type = 1
) T ON T.wr_wo_id = wr.wr_wo_id
WHERE T.wr2.wr_wo_id IS NULL
AND (w.wo_type = 1 or w.wo_type = 2)
AND wr.wr_row_type = 2
AND w.wo_lo_id like '%'
AND w.wo_date_time >= '2010-01-01' AND w.wo_date_time <= '2010-01-31'
GROUP BY wr.wr_re_id
Cependant, il est plus facile à lire et (je suppose, essayer si elle) plus efficace utiliser:
SELECT wr.wr_re_id as ReID, sum(wr.wr_total) as PRTotal
FROM Workorder2 w
INNER JOIN Workorder_Row2 wr on wr.wr_wo_id = w.wo_id
WHERE (w.wo_type = 1 or w.wo_type = 2)
AND wr.wr_row_type = 2
AND w.wo_lo_id like '%'
AND w.wo_date_time >= '2010-01-01' AND w.wo_date_time <= '2010-01-31'
AND NOT EXISTS (
SELECT NULL
FROM Workorder_Row2 wr2
INNER JOIN Workorder2 w2 on w2.wo_id = wr2.wr_wo_id
WHERE w2.wo_date_time >= '2010-01-01'
AND w2.wo_date_time <= '2010-01-31'
AND wr2.wr_row_type = 1
AND wr2.wr_wo_id = wr.wr_wo_id
)
GROUP BY wr.wr_re_id
La première étape devrait être d'obtenir le plan de requête à partir de votre base de données, cela vous montrera où de longues analyses de table se produisent. – Paolo
'ET w.wo_lo_id comme '%'' semble mortel pour moi – Natrium
@Natrium cette déclaration est fondamentalement dire w.wo_lo_id peut être n'importe quoi, même "", mais pas NULL. J'espère que l'optimiseur de requêtes l'attrape. –