モジュールのレッスン (4/4)
グループのフィルタリング: HAVING
グループごとの結果が得られたら (前のレッスン)、多くの場合、
条件を満たすグループのみを保持: より多くのグループを持つ部門
2 人以上、平均予算が 100,000 を超えるプロジェクト、
少なくとも10個の注文。これを行うには、WHERE だけでは十分ではありません。
WHERE だけでは不十分な理由
WHERE は、集計の前に テーブル行をフィルター処理します。だからそれは見えない
COUNT(*) または AVG(...) の結果: WHERE が実行されるまでに、それらは
値はまだ計算されていません。
-- ERROR: COUNT(*) doesn't exist yet when WHERE is evaluated
SELECT department_id, COUNT(*) AS count
FROM employees
WHERE COUNT(*) > 2 -- ❌ doesn't work
GROUP BY department_id;後の集計をフィルタリングするには、HAVING という専用の句があります。
構文
SELECT grouping_column, AGGREGATE_FUNCTION(...)
FROM table
GROUP BY grouping_column
HAVING condition_on_aggregate;-- Departments with more than 2 employees:
SELECT department_id, COUNT(*) AS count
FROM employees
GROUP BY department_id
HAVING COUNT(*) > 2;HAVING は GROUP BY に対して、WHERE は FROM に対して、同じ考えです。
(「フィルター」) ただし、グループ化後、集計に適用されます。
句の論理的な順序
WHERE と HAVING を再び混同しないように、その順序を覚えておいてください。
SQL はそれらを精神的に実行します。
FROM/JOIN— ソースを結合して開始テーブルを構築します。WHERE— 関係のない行を削除します。GROUP BY— 残りの行をグループに収集します。HAVING— 関係のないグループを削除します。SELECT— 最終列 (集計を含む) を計算します。ORDER BY/LIMIT— 並べ替えて切り取ります。
重要な注意事項:
WHEREでは テーブル列 のみを使用できます。HAVINGでは 列と集計のグループ化を使用できます。
-- Classic combo: filter first, group, filter the groups, sort.
SELECT d.name, AVG(e.salary) AS average
FROM employees AS e
JOIN departments AS d ON e.department_id = d.id
WHERE e.hired_on >= '2018-01-01' -- filter rows
GROUP BY d.name
HAVING AVG(e.salary) > 35000 -- filter groups
ORDER BY average DESC;試してみてください
各部門の名前 (Departments.name) と従業員数を表示します。ただし、従業員が 2 人以上いる部門のみです。 2 列、対象となる部門ごとに 1 行。
ヒントを表示
「少なくとも 2」条件は、HAVING では COUNT(*) >= 2 になります。
3 回の試行後に解決策が利用可能になります
復習演習
平均給与が 35000 を超える部門 (部門名) を表示します。2018 年以降に雇用された従業員のみを考慮します。 2 つの列: 名前と平均。平均の降順で並べ替えます。
ヒントを表示
WHERE は行 (2018 年から雇用された従業員) をフィルターし、HAVING はグループ (平均 > 35000) をフィルターします。
3 回の試行後に解決策が利用可能になります