Тъй като тези три агрегата идват от една и съща таблица с едно и също WHERE
условия, нямате нужда от подизбори. И трите агрегата работят на едно и също групиране на редове (без GROUP BY
посочени, така че един ред за цялата таблица), така че всички те могат да съществуват в SELECT
списък директно.
SELECT
SUM(number) AS number_sum,
MAX(number) AS number_max,
MIN(number) AS number_min
FROM `table`
Ако някоя от агрегатите трябва да се базира на различни условия, бихте филтрирали в WHERE
клауза, тогава ще трябва или да използвате подизбор за различното условие, или да направите декартово свързване. Този подизбор и следното LEFT JOIN
методът трябва да е еквивалентен по отношение на производителността за агрегати, връщащи само един ред:
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`
Или еквивалентно на заявката по-горе, можете да LEFT JOIN
срещу подзаявка без ON
клауза . Това трябва да се прави само в ситуации, когато знаете, че подзаявката ще върне само един ред. В противен случай ще получите декартово произведение -- толкова реда, колкото са върнати от едната страна на съединението, умножено по броя на редовете, върнати от другата страна.
Това е удобно, ако трябва да върнете няколко колони с един набор от WHERE
условия на клауза и няколко колони с различен набор от WHERE
условия, но само един ред от всяка страна на JOIN
. В този случай би трябвало да е по-бързо JOIN
отколкото да направя две подизбира със същия WHERE
клауза.
Това трябва да е по-бързо....
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... */
От това...
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`