Como esses três agregados vêm da mesma tabela com o mesmo
WHERE
condições, você não precisa de subseleções. Todos os três agregados estão operando no mesmo agrupamento de linhas (sem GROUP BY
especificado, então uma linha para toda a tabela), para que todos possam existir no SELECT
lista diretamente. SELECT
SUM(number) AS number_sum,
MAX(number) AS number_max,
MIN(number) AS number_min
FROM `table`
Se algum dos agregados precisar ser baseado em condições diferentes, você filtrará em um
WHERE
cláusula, então você precisará usar uma subseleção para a condição diferente ou fazer uma junção cartesiana. Esta subseleção e o seguinte LEFT JOIN
O método deve ser equivalente, em termos de desempenho, para agregações que retornam apenas uma linha: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 equivalente à consulta acima, você pode
LEFT JOIN
contra uma subconsulta sem ON
cláusula . Isso só deve ser feito em situações em que você sabe que a subconsulta retornará apenas uma linha. Caso contrário, você terá um produto cartesiano -- quantas linhas forem retornadas por um lado da junção multiplicado por o número de linhas retornadas pelo outro lado. Isso é útil se você precisar retornar algumas colunas com um conjunto de
WHERE
condições da cláusula e algumas colunas com um conjunto diferente de WHERE
condições, mas apenas uma linha de cada lado do JOIN
. Nesse caso, deve ser mais rápido JOIN
do que fazer dois subseleções com o mesmo WHERE
cláusula. Isso deve ser mais rápido....
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... */
Do que isso...
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`