【ITニュース解説】SQL GROUP BY Explained with Examples
2025年09月24日に「Dev.to」が公開したITニュース「SQL GROUP BY Explained with Examples」について初心者にもわかりやすく解説しています。
ITニュース概要
SQLのGROUP BY句は、同じ値を持つ行をグループ化し、COUNT、SUM、AVGなどの集計関数でデータ分析に役立つ。顧客ごとの注文数や合計金額の算出などが可能で、HAVING句でグループ化後の条件絞り込みもできる。複雑なデータから意味ある要約を作成する強力なツールだ。
ITニュース解説
データベースを扱う際、個々のデータ(生データ)をただ眺めるだけでなく、それらをまとめて「合計」「平均」「数」といった意味のある情報(集計データ、サマリー)として把握したい場面が頻繁に訪れる。例えば、「各顧客が何回注文したか」「部門ごとの合計売上はいくらか」「生徒ごとの平均点は何か」といった、特定の条件でデータをまとめた上で集計するような疑問に答える際に、SQLのGROUP BY句が非常に役立つ。
GROUP BY句は、データベースのテーブルから取得した行の中から、指定した列で同じ値を持つものを一つの「グループ」としてまとめ上げる機能を持つ。そして、そのまとめたグループに対して、COUNT()、SUM()、AVG()、MIN()、MAX()といった集計関数を適用することで、グループごとの集計結果を得ることができる。
このGROUP BYの基本的な使い方から見ていこう。まず、あるショップのデータベースを想定し、顧客とその注文に関する情報を扱う。Ordersというテーブルがあり、顧客ID(customer_id)や注文金額(total_amount)などの情報が格納されているとする。
最初に、各顧客が何件の注文を行ったかを知りたい場合を考える。これは、Ordersテーブルの各行をcustomer_idでグループ化し、それぞれのグループに含まれる行の数を数えることで実現できる。
SELECT customer_id, COUNT(*) AS order_count FROM Orders GROUP BY customer_id;
このSQLクエリを実行すると、それぞれのcustomer_idごとにOrdersテーブルの行がグループ化され、各グループに属する行の数、つまり各顧客の注文数がorder_countという名前で表示される。
次に、各顧客が合計でいくら使ったか、つまり顧客ごとの合計購入金額を知りたい場合はどうだろうか。Ordersテーブルには注文ごとの合計金額を示すtotal_amount列がある。
SELECT customer_id, SUM(total_amount) AS total_spent FROM Orders GROUP BY customer_id;
このクエリでは、customer_idごとにグループ化された各顧客のtotal_amount列の値を全て合計し、その顧客が使った合計金額がtotal_spentという名前で結果として得られる。
しかし、customer_idだけでは、どの顧客が誰なのか直感的に分かりにくい場合がある。そこで、顧客の名前を保持するCustomersという別のテーブルを導入する。このテーブルにはcustomer_idとnameの列があるとしよう。OrdersテーブルとCustomersテーブルは、共通のcustomer_id列を使って関連付けることができる。このようなテーブル間の関連付けを行うのがJOIN句である。JOINを使うことで、customer_idのような数値のIDではなく、nameのような人間が理解しやすい情報を集計結果に表示できるようになる。
顧客名を結果に含めて、各顧客の平均注文金額を知りたい場合は、JOINとAVG()を組み合わせて使う。
SELECT c.name, AVG(o.total_amount) AS avg_order FROM Customers c JOIN Orders o ON c.customer_id = o.customer_id GROUP BY c.name;
このクエリでは、Customersテーブルをc、Ordersテーブルをoという別名で呼び、customer_id列で両者を結合している。そして、c.nameで顧客名を指定してグループ化し、各顧客のtotal_amountの平均を計算する。例えば、サラという顧客が50と70の2つの注文をしていた場合、その平均は60として表示される。
さらに、集計された結果に対して、特定の条件でフィルタリングを行いたい場合がある。例えば、「合計購入金額が50を超える顧客だけを表示する」といったケースだ。このような「グループ化された結果」に対する条件付けにはHAVING句を使用する。WHERE句はグループ化が行われる前の個々の行に条件を適用するのに対し、HAVING句は集計関数が適用された後のグループ全体に条件を適用するという違いがある。
SELECT c.name, SUM(o.total_amount) AS total_spent FROM Customers c JOIN Orders o ON c.customer_id = o.customer_id GROUP BY c.name HAVING SUM(o.total_amount) > 50;
このクエリは、まず各顧客の合計購入金額を計算し、その後にHAVING句の条件によって、合計金額が50より大きい顧客だけを結果として表示する。
GROUP BYは、MIN()(最小値)やMAX()(最大値)といった集計関数と組み合わせることもできる。例えば、各顧客の最小注文金額や最大注文金額を知りたい場合は以下のようになる。
各顧客の最小注文金額: SELECT c.name, MIN(o.total_amount) AS min_order FROM Customers c JOIN Orders o ON c.customer_id = o.customer_id GROUP BY c.name;
各顧客の最大注文金額: SELECT c.name, MAX(o.total_amount) AS max_order FROM Customers c JOIN Orders o ON c.customer_id = o.customer_id GROUP BY c.name;
これらのクエリは、それぞれ顧客ごとの最も低い注文金額、最も高い注文金額を返してくれる。
まとめると、GROUP BY句はデータベースの生データを意味のある集計情報に変換するために不可欠な機能である。COUNT()、SUM()、AVG()、MIN()、MAX()といった集計関数と組み合わせて使用し、HAVING句で集計後のフィルタリングを行うことができる。また、JOIN句を使うことで、関連するテーブルから情報を取得し、より人間が理解しやすい形で結果を表示することが可能になる。
DbSchemaのようなデータベースツールには、SQLクエリを直接書かなくても、テーブルをドラッグ&ドロップし、集計関数を選択するだけでGROUP BYクエリを視覚的に構築できるものもある。このようなツールは、SQLの学習を補助し、クエリの構造を理解する上で役立つだろう。GROUP BYは、合計、平均、カテゴリ別のレポートなど、多くのビジネスレポート作成の基盤となる重要な概念であり、システムエンジニアを目指す上で確実に身につけておくべき知識である。