Eftersom dessa tre aggregat kommer från samma tabell med samma WHERE
villkor har du inget behov av underval. Alla tre aggregaten arbetar på samma radgruppering (ingen GROUP BY
specificerade, alltså en rad för hela tabellen), så att de alla kan finnas i SELECT
lista direkt.
SELECT
SUM(number) AS number_sum,
MAX(number) AS number_max,
MIN(number) AS number_min
FROM `table`
Om något av aggregaten behöver baseras på olika villkor skulle du filtrera in en WHERE
klausul, då måste du antingen använda ett underval för det olika villkoret eller göra en kartesisk join. Detta underval och följande LEFT JOIN
Metoden bör vara likvärdig, prestandamässigt för aggregat som endast returnerar en rad:
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`
Eller motsvarande frågan ovan, du kan LEFT JOIN
mot en underfråga utan ON
klausul . Detta bör endast göras i situationer när du vet att underfrågan endast kommer att returnera en rad. Annars kommer du att få en kartesisk produkt -- lika många rader som returneras av en sida av sammanfogningen multiplicerad med antalet rader som returneras av den andra sidan.
Detta är praktiskt om du behöver returnera några kolumner med en uppsättning WHERE
klausulvillkor och några kolumner med en annan uppsättning WHERE
villkor, men bara ett rad från varje sida av JOIN
. I det här fallet borde det gå snabbare att JOIN
än att göra två underval med samma WHERE
klausul.
Detta borde vara snabbare...
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... */
Än så här...
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`