Protože tyto tři agregáty pocházejí ze stejné tabulky se stejným WHERE
podmínky, nepotřebujete podvýběry. Všechny tři agregáty fungují na stejném seskupení řádků (bez GROUP BY
zadané, takže jeden řádek pro celou tabulku), takže mohou všechny existovat v SELECT
vypsat přímo.
SELECT
SUM(number) AS number_sum,
MAX(number) AS number_max,
MIN(number) AS number_min
FROM `table`
Pokud je třeba, aby některý z agregátů vycházel z různých podmínek, filtrovali byste pomocí WHERE
klauzuli, pak budete muset buď použít podvýběr pro odlišnou podmínku, nebo provést kartézské spojení. Tento dílčí výběr a následující LEFT JOIN
metoda by měla být z hlediska výkonu ekvivalentní pro agregáty vracející pouze jeden řádek:
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`
Nebo ekvivalentně k výše uvedenému dotazu můžete LEFT JOIN
proti poddotazu bez ON
doložka . To by mělo být provedeno pouze v situacích, kdy víte, že poddotaz vrátí pouze jeden řádek. V opačném případě skončíte s kartézským součinem – tolik řádků, kolik vrátí jedna strana spojení násobeno počet řádků vrácených druhou stranou.
To je užitečné, pokud potřebujete vrátit několik sloupců s jednou sadou WHERE
podmínky klauzule a několik sloupců s jinou sadou WHERE
podmínky, ale pouze jednu řádek z každé strany JOIN
. V tomto případě by mělo být rychlejší JOIN
než udělat dva podvýběry se stejným WHERE
doložka.
To by mělo být rychlejší....
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... */
Než toto...
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`