sql >> Base de Datos >  >> RDS >> Mysql

MySQL Múltiples Subconsultas vs. consultas completas

Dado que estos tres agregados provienen de la misma tabla con el mismo WHERE condiciones, no necesita subselecciones. Los tres agregados están operando en la misma agrupación de filas (sin GROUP BY especificado, por lo que una fila para toda la tabla), por lo que todos pueden existir en el SELECT lista directamente.

SELECT
  SUM(number) AS number_sum,
  MAX(number) AS number_max,
  MIN(number) AS number_min
FROM `table`

Si alguno de los agregados debe basarse en diferentes condiciones, filtraría en WHERE cláusula, entonces deberá usar una subselección para la condición diferente o hacer una unión cartesiana. Esta subselección y la siguiente LEFT JOIN El método debe ser equivalente, en cuanto al rendimiento, para los agregados que devuelven solo una fila:

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`

O equivalente a la consulta anterior, puede LEFT JOIN contra una subconsulta sin ON cláusula . Esto solo debe hacerse en situaciones en las que sabe que la subconsulta devolverá solo una fila. De lo contrario, terminará con un producto cartesiano:tantas filas como devuelva un lado de la combinación multiplicadas por el número de filas devueltas por el otro lado.

Esto es útil si necesita devolver algunas columnas con un conjunto de WHERE condiciones de la cláusula y algunas columnas con un conjunto diferente de WHERE condiciones, pero solo una fila de cada lado de JOIN . En este caso, debería ser más rápido JOIN que hacer dos subselecciona con el mismo WHERE cláusula.

Esto debería ser más 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... */

Que esto...

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`