Puisque ces trois agrégats proviennent de la même table avec le même WHERE
conditions, vous n'avez pas besoin de sous-sélections. Les trois agrégats fonctionnent sur le même groupement de lignes (pas de GROUP BY
spécifié, donc une ligne pour toute la table), afin qu'ils puissent tous exister dans le SELECT
liste directement.
SELECT
SUM(number) AS number_sum,
MAX(number) AS number_max,
MIN(number) AS number_min
FROM `table`
Si l'un des agrégats doit être basé sur des conditions différentes, vous filtrerez dans un WHERE
clause, vous devrez soit utiliser une sous-sélection pour la condition différente, soit effectuer une jointure cartésienne. Cette sous-sélection et le LEFT JOIN
suivant doit être équivalente, en termes de performances, pour les agrégats ne renvoyant qu'une seule ligne :
SELECT
/* Unique filtering condition - must be done in a subselect */
(SELECT SUM(number) FROM `table` WHERE `somecolumn` = `somevalue`) AS number_sum,
MAX(number) AS number_max,
MIN(number) AS number_min
FROM `table`
Ou équivalent à la requête ci-dessus, vous pouvez LEFT JOIN
contre une sous-requête sans ON
clause . Cela ne doit être fait que dans les situations où vous savez que la sous-requête ne renverra qu'une seule ligne. Sinon, vous vous retrouverez avec un produit cartésien - autant de lignes renvoyées par un côté de la jointure multipliées par le nombre de lignes renvoyées par l'autre côté.
C'est pratique si vous devez renvoyer quelques colonnes avec un ensemble de WHERE
conditions de clause et quelques colonnes avec un ensemble différent de WHERE
conditions, mais seulement une ligne de chaque côté du JOIN
. Dans ce cas, il devrait être plus rapide de JOIN
que d'en faire deux sous-sélectionne avec le même WHERE
clause.
Cela devrait être plus rapide....
SELECT
/* this one has two aggregates sharing a WHERE condition */
subq.number_sum_filtered,
subq.number_max_filtered,
/* ...and two aggregates on the main table with no WHERE clause filtering */
MAX(`table`.number) AS number_max,
MIN(`table`.number) AS number_min
FROM
`table`
LEFT JOIN (
SELECT
SUM(number) AS number_sum_filtered,
MAX(number) AS number_max_filtered
FROM `table`
WHERE `somecolumn = `somevalue`
) subq /* No ON clause here since there's no common column to join on... */
Plus que ça...
SELECT
/* Two different subselects each over the same filtered set */
(SELECT SUM(number) FROM `table` WHERE `somecolumn` = `somevalue`) AS number_sum_filtered,
(SELECT MAX(number) FROM `table` WHERE `somecolumn` = `somevalue`) AS number_max_filtered,
MAX(`table`.number) AS number_max,
MIN(`table`.number) AS number_min
FROM
`table`