2

MySQLデータベースからデータを取得する方法の方がパフォーマンス特性が優れているのではないかと思います。

1つのメインクエリ内でサブクエリを使用する:

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

または、SELECT同じデータを取得する3つの異なるステートメント。

前もって感謝します!

4

1 に答える 1

8

これらの3つの集計は同じ条件の同じテーブルからのものでWHEREあるため、副選択は必要ありません。3つのアグリゲートはすべて同じ行グループで動作しているため(GROUP BY指定されていないため、テーブル全体で1つの行)、すべてをSELECTリストに直接存在させることができます。

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

集約のいずれかが、句でフィルタリングするさまざまな条件に基づく必要がある場合はWHERE、さまざまな条件の副選択を使用するか、デカルト結合を実行する必要があります。この副選択と次のLEFT JOINメソッドは、1つの行のみを返す集計の場合、パフォーマンス的に同等である必要があります。

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サブクエリに対して実行できます。これは、サブクエリが1行のみを返すことがわかっている状況でのみ実行する必要があります。そうしないと、デカルト積になってしまいます。つまり、結合の一方の側から返された行数に、もう一方の側から返された行の数を掛けたものになります。ON

WHEREこれは、1セットの句条件を持ついくつかの列と異なる条件セットを持ついくつかの列を返す必要があるが、の両側から1WHERE行だけを返す必要がある場合に便利です。この場合、同じ句で2つの副選択を実行するよりも高速である必要があります。JOINJOINWHERE

これはもっと速いはずです…。

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`
于 2012-09-03T01:31:15.710 に答える