sql >> Databasteknik >  >> RDS >> Mysql

MySQL Multiple Subqueries vs. hela frågor

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`



  1. Hämta en enda rad från Join Table

  2. visa tabeller med liknande använda Java och MySQL?

  3. Hur man infogar stora mängder data i sqlite-databasen i Android

  4. MySQL - autoincrement till guid