SQLの使用に関するいくつかの重要なポイント:
- WHERE句では列エイリアスを使用できませんが、HAVING句では使用できます。それがエラーの原因です。
- 相関サブクエリを使用するよりも、JOINとGROUPBYを使用した方がカウントを向上させることができます。はるかに高速になります。
- HAVING句を使用してグループをフィルタリングします。
このクエリの書き方は次のとおりです。
SELECT t1.id, COUNT(t2.id) AS num_things
FROM t1 JOIN t2 USING (id)
GROUP BY t1.id
HAVING num_things = 5;
このクエリはJOIN
をスキップできることに気付きました Charles Bretanaのソリューションのように、t1を使用します。ただし、クエリにt1の他の列を含めることをお勧めします。
Re:コメントの質問:
違いは、WHERE
句は、GROUP BY
の前の行で評価されます グループをグループごとに1行に減らします。 HAVING
グループが形成された後、句が評価されます。したがって、たとえば、COUNT()
を変更することはできません。 HAVING
を使用したグループの;グループ自体のみを除外できます。
SELECT t1.id, COUNT(t2.id) as num
FROM t1 JOIN t2 USING (id)
WHERE t2.attribute = <value>
GROUP BY t1.id
HAVING num > 5;
上記のクエリでは、WHERE
条件に一致する行のフィルター、およびHAVING
少なくとも5つのカウントを持つグループのフィルター。
ほとんどの人が混乱するのは、GROUP BY
がない場合です。 句なので、そうです HAVING
のように およびWHERE
交換可能です。
WHERE
選択リストの式の前に評価されます。 SQL構文では選択リストが最初に配置されるため、これは明らかではない場合があります。したがって、WHERE
を使用すると、コストのかかる計算を大幅に節約できます。 行を制限します。
SELECT <expensive expressions>
FROM t1
HAVING primaryKey = 1234;
上記のようなクエリを使用する場合、選択リストの式はすべての行に対して計算されます。 、HAVING
のため、ほとんどの結果を破棄するだけです 調子。ただし、以下のクエリは、単一行の式のみを計算します。 WHERE
と一致する 状態。
SELECT <expensive expressions>
FROM t1
WHERE primaryKey = 1234;
要約すると、クエリは一連の手順に従ってデータベースエンジンによって実行されます。
-
JOIN
によって生成された行を含め、テーブルから行のセットを生成します 。 WHERE
を評価する 行のセットに対する条件、一致しない行を除外します。- 行セット内のそれぞれの選択リストで式を計算します。
- 列エイリアスを適用します(これは別の手順であるため、選択リストの式でエイリアスを使用することはできません)。
-
GROUP BY
に従って、グループをグループごとに1行に凝縮します。 条項。 -
HAVING
を評価する グループに対する条件、一致しないグループを除外します。 -
ORDER BY
に従って結果を並べ替えます 条項。