Ponieważ te trzy agregaty pochodzą z tej samej tabeli z tym samym WHERE
warunki, nie potrzebujesz podselekcji. Wszystkie trzy agregaty działają na tym samym grupowaniu wierszy (bez GROUP BY
określony, więc jeden wiersz dla całej tabeli), aby wszystkie mogły istnieć w SELECT
lista bezpośrednio.
SELECT
SUM(number) AS number_sum,
MAX(number) AS number_max,
MIN(number) AS number_min
FROM `table`
Jeśli którykolwiek z agregatów musi być oparty na różnych warunkach, filtrujesz w WHERE
, wtedy będziesz musiał albo użyć podselekcji dla innego warunku, albo wykonać złączenie kartezjańskie. Ten podwybór i następujące LEFT JOIN
metoda powinna być równoważna, pod względem wydajności dla agregatów zwracających tylko jeden wiersz:
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`
Lub odpowiednik powyższego zapytania, możesz LEFT JOIN
przeciwko podzapytaniu bez ON
klauzula . Należy to robić tylko w sytuacjach, gdy wiadomo, że podzapytanie zwróci tylko jeden wiersz. W przeciwnym razie otrzymasz produkt kartezjański — tyle wierszy, ile zwróci jedna strona połączenia pomnożona przez liczba wierszy zwróconych przez drugą stronę.
Jest to przydatne, jeśli chcesz zwrócić kilka kolumn z jednym zestawem WHERE
warunki klauzuli i kilka kolumn z innym zestawem WHERE
warunki, ale tylko jeden wiersz z każdej strony JOIN
. W takim przypadku powinno być szybciej JOIN
niż zrobić dwa podselekcje z tym samym WHERE
klauzula.
To powinno być szybsze....
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... */
Niż to...
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`