sql >> Database teknologi >  >> RDS >> Mysql

MySQL Multiple Subqueries vs. hele forespørgsler

Da disse tre aggregater kommer fra den samme tabel med den samme WHERE betingelser, har du ikke behov for undervalg. Alle tre aggregater arbejder på den samme rækkegruppering (ingen GROUP BY specificeret, så en række for hele tabellen), så de alle kan eksistere i SELECT liste direkte.

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

Hvis nogen af ​​aggregaterne skal være baseret på forskellige betingelser, vil du filtrere i en WHERE klausul, så skal du enten bruge et undervalg til den afvigende betingelse eller lave en kartesisk joinforbindelse. Dette undervalg og følgende LEFT JOIN metoden skal være ækvivalent, præstationsmæssigt for aggregater, der kun returnerer én række:

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 svarende til forespørgslen ovenfor, du kan LEFT JOIN mod en underforespørgsel uden ON klausul . Dette bør kun gøres i situationer, hvor du ved, at underforespørgslen kun vil returnere én række. Ellers vil du ende med et kartesisk produkt -- lige så mange rækker, som returneres af den ene side af sammenføjningen multipliceret med antallet af rækker returneret af den anden side.

Dette er praktisk, hvis du har brug for at returnere et par kolonner med ét sæt WHERE klausulbetingelser og nogle få kolonner med et andet sæt WHERE betingelser, men kun én række fra hver side af JOIN . I dette tilfælde burde det være hurtigere at JOIN end at gøre to undervælger med den samme WHERE klausul.

Dette burde være hurtigere...

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... */

End dette...

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. Hvordan løses MySQL innodb Venter på tabelmetadatalås på TRUNCATE TABLE?

  2. MySQL:Langsom log; tilføje CPU-brug

  3. datetime vs datetime2 i SQL Server:Hvad er forskellen?

  4. Ulovligt forsøg på at kortlægge en ikke-samling som en @OneToMany, @ManyToMany eller @CollectionOfElements