目次
ヒント: HAVING はすべての WHERE 演算子をサポートします
データパケット
グループ化を使用してデータを論理グループに分割し、各グループで集計計算を実行します。
グループを作る
グループ化は、SELECT ステートメントの GROUP BY 句を使用して確立されます。グループ化を理解する最良の方法は、例を見ることです。
SELECT vend_id, COUNT(*) AS num_prods FROM Products GROUP BY vend_id;
GROUP BY を使用しているため、計算および評価する各グループを指定する必要はありません。システムが自動的に行います。GROUP BY 句は、データをグループ化し、結果セット全体ではなく各グループを集計するように DBMS に指示します。
GROUP BY の使用規則:
- GROUP BY 句には任意の数の列を含めることができるため、グループをネストして、より詳細なデータ グループ化を行うことができます。
- GROUP BY 句にネストされたグルーピングがある場合、データは最後に指定されたグルーピングで集計されます。つまり、グループ化が作成されると、指定されたすべての列がまとめて計算されます (そのため、個々の列からデータを取得することはできません)。
- GROUP BY 句にリストされている各列は、検索列または有効な式 (ただし、集計関数ではない) である必要があります。SELECT で式を使用する場合、同じ式を GROUP BY 句で指定する必要があります。エイリアスは使用できません。
- ほとんどの SQL 実装では、可変長データ型 (テキスト フィールドやメモ フィールドなど) の GROUP BY 列を使用できません。
- 集計計算ステートメントを除き、SELECT ステートメントのすべての列を GROUP BY 句で指定する必要があります。
- グループ化列に NULL 値の行が含まれている場合、グループとして NULL が返されます。列に NULL 値の行が複数ある場合は、グループ化されます。
- GROUP BY 句は、WHERE 句の後、ORDER BY 句の前に配置する必要があります。
ALL句
Microsoft SQL Server などの一部の SQL 実装では、GROUP BY でオプションの ALL 句がサポートされています。この句を使用すると、一致する行がないグループも含めて、すべてのグループを返すことができます (この場合、集計は NULL を返します)。特定の DBMS が ALL をサポートしているかどうかについては、対応するドキュメントを参照してください。
フィルタ グループ
WHERE 句の動作については既に説明しました (レッスン 4 で説明)。ただし、 WHERE フィルターはグループではなく行を指定するため、この例では WHERE は機能しません。実際、WHERE にはグループ化の概念がありません。
では、WHERE の代わりに何を使用すればよいでしょうか。SQL では、この目的のために HAVING 句という別の句が提供されています。HAVING は WHERE とよく似ています。実際、これまでに学習したすべてのタイプの WHERE 句は、HAVING に置き換えることができます。唯一の違いは、WHERE は行をフィルター処理するのに対し、HAVING はグループをフィルター処理することです。
ヒント: HAVING はすべての WHERE 演算子をサポートします
レッスン 4 と 5 では、WHERE 句の条件 (ワイルドカード条件と複数の演算子を含む句を含む) について学習しました。WHERE について学んだすべてのテクニックとオプションは、HAVING に適用されます。構文は同じで、キーワードのみが異なります。
SELECT cust_id, COUNT(*) AS orders FROM Orders GROUP BY cust_id HAVING COUNT(*) >= 2;
場合によっては、特定の条件を満たす必要があり、同時に1より大きい数のデータを取得する必要がある場合や、2以上の数のデータが必要な場合があります。この場合、havingを使用するのが適切です。(カウント(*) >= 2;)
HAVING と WHERE の違い
データのグループ化の前に WHERE フィルターを使用し、データのグループ化の後に HAVING フィルターを使用して理解する別の方法を次に示します。これは重要な違いです。WHERE によって除外された行はグループ化に含まれません。これにより、計算された値が変更される可能性があり、HAVING 句の値に基づいて除外されるグループ化に影響します。
では、1 つのステートメントで WHERE 句と HAVING 句の両方を使用する必要はありますか? 実際、あります。過去 12 か月間に 2 回以上注文した顧客を返すように、上記のステートメントをさらにフィルター処理するとします。これを行うには、WHERE 句を追加して過去 12 か月以内に行われた注文を除外し、次に HAVING 句を追加して 3 つ以上の注文があるグループを除外します。理解を深めるために、次の例を見てください。価格が 4 以上の製品を 3 つ以上持つサプライヤが一覧表示されています。
SELECT vend_id, COUNT(*) AS num_prods
FROM Products
WHERE prod_price >= 4
GROUP BY vend_id
HAVING COUNT(*) >= 2;
このステートメントの最初の行は、前の例と同様に、集計関数を使用する基本的な SELECT ステートメントです。WHERE 句は、prod_price が 4 以上のすべての行をフィルタリングしてから、データを vendor_id でグループ化し、HAVING 句はカウントが 2 以上のグループをフィルタリングします。WHERE 句がない場合は、もう 1 行が取得されます (サプライヤー DLL01、4 つの製品を販売し、すべての価格が 4 未満)
SELECT vend_id, COUNT(*) AS num_prods
FROM Products
GROUP BY vend_id
HAVING COUNT(*) >= 2;
HAVING と WHERE の使用
HAVING は WHERE と非常に似ており、GROUP BY を指定しない場合、ほとんどの DBMS はそれらを同等に扱います。ただし、これを自分で区別できる必要があります。HAVING は GROUP BY 句と組み合わせて使用する必要がありますが、WHERE 句は標準の行レベルのフィルタリングに使用されます。
グループ化とソート
GROUP BY と ORDER BY はしばしば同じことを行いますが、大きく異なることを理解することが重要です。以下の表は、それらの違いをまとめたものです。
表に記載されている最初の違いは非常に重要です。GROUP BY でグループ化されたデータが実際にグループ順に出力されることがよくあります。しかし、常にそうであるとは限りません。SQL 仕様で要求されているわけではありません。また、特定の DBMS が特定の GROUP BY 句によって常にデータを並べ替える場合でも、ユーザーはデータを別の順序で並べ替えるように要求する場合があります。(特定のグループ化された集計値を取得するために) 特定の方法でデータをグループ化したからといって、同じ方法で出力を並べ替える必要があるわけではありません。GROUP BY 句と同等であっても、明示的な ORDER BY 句を指定する必要があります。
簡単に言えばGROUP BYでグループ化しますが、出力結果が昇順/降順で出力されない場合がありますので、昇順/降順にする場合はOrder by句を使用してください。
ORDER BY を忘れないでください
通常、GROUP BY 句を使用する場合は、ORDER BY 句も指定する必要があります。これは、データが正しくソートされることを保証する唯一の方法です。GROUP BY だけに頼ってデータを並べ替えないでください。
GROUP BY と ORDER BY の使用法を説明するために、例を見てみましょう。次の SELECT ステートメントは、前の例と似ています。3 つ以上の商品の注文番号と注文数を取得します。
SELECT order_num, COUNT(*) AS items
FROM OrderItems
GROUP BY order_num
HAVING COUNT(*) >= 3;
注文されたアイテムの数で出力を並べ替えるには、次のように ORDER BY 句を追加する必要があります。
SELECT order_num, COUNT(*) AS items
FROM OrderItems
GROUP BY order_num
HAVING COUNT(*) >= 3
ORDER BY items, order_num;
order_num アイテム
--------- -----
20009 3
20007 5
20008 5
この例では、GROUP BY 句を使用してデータを注文番号 (order_num 列) でグループ化し、COUNT(*) 関数が各注文の項目数を返すようにします。HAVING 句はデータをフィルタリングして、3 つ以上のアイテムを含む注文のみが返されるようにします。最後に、ORDER BY 句を使用して出力を並べ替えます。
SELECT 句の順序
SELECT ステートメントの句の順序を確認してみましょう。次の表は、これまでに学習した句を、SELECT ステートメントで使用する必要がある順序で示しています。