MySQLの単一クエリでGROUP BY・HAVING・ORDER BYを組み合わせ、合計値が特定範囲内のレコードを表示する方法
はじめに
MySQLでは、GROUP BY句でグループ化し、HAVING句で集計結果に条件を付け、ORDER BY句で並べ替えるという一連の処理を、たった1つのクエリで実行できます。本記事では「顧客ごとの商品価格の合計が1600〜2000の範囲内にあるレコードだけを抽出する」具体例を使って、手順をわかりやすく解説します。
ステップ1:サンプルテーブルを作成する
まず、デモ用のテーブルを作成します。
mysql> create table DemoTable
(
Id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
CustomerName varchar(20),
ProductPrice int
);
Query OK, 0 rows affected (0.70 sec)
ステップ2:レコードを挿入する
次に、INSERTコマンドで複数のレコードを追加します。同じ顧客名(Chris、David)が複数回登場するようにしているのがポイントです。
mysql> insert into DemoTable(CustomerName,ProductPrice) values('Chris',600);
Query OK, 1 row affected (0.18 sec)
mysql> insert into DemoTable(CustomerName,ProductPrice) values('David',450);
Query OK, 1 row affected (0.09 sec)
mysql> insert into DemoTable(CustomerName,ProductPrice) values('Chris',980);
Query OK, 1 row affected (0.40 sec)
mysql> insert into DemoTable(CustomerName,ProductPrice) values('Mike',1200);
Query OK, 1 row affected (0.11 sec)
mysql> insert into DemoTable(CustomerName,ProductPrice) values('Chris',400);
Query OK, 1 row affected (0.11 sec)
mysql> insert into DemoTable(CustomerName,ProductPrice) values('David',1200);
Query OK, 1 row affected (0.20 sec)
ステップ3:登録したデータを確認する
SELECT文を実行して、テーブルの中身を確認してみましょう。
mysql> select *from DemoTable;
実行結果は以下の通りです。
+----+--------------+--------------+ | Id | CustomerName | ProductPrice | +----+--------------+--------------+ | 1 | Chris | 600 | | 2 | David | 450 | | 3 | Chris | 980 | | 4 | Mike | 1200 | | 5 | Chris | 400 | | 6 | David | 1200 | +----+--------------+--------------+ 6 rows in set (0.00 sec)
ステップ4:GROUP BY・HAVING・ORDER BYを組み合わせたクエリ
それでは本題のクエリです。顧客名ごとに商品価格の合計を算出し、その合計が1600以上2000以下であるグループだけを抽出して、顧客名の降順で表示しています。
mysql> select CustomerName,sum(ProductPrice) AS Total_Price
from DemoTable
group by CustomerName
having sum(ProductPrice) between 1600 and 2000
order by CustomerName DESC;
実行結果は以下の通りです。
+--------------+-------------+ | CustomerName | Total_Price | +--------------+-------------+ | David | 1650 | | Chris | 1980 | +--------------+-------------+ 2 rows in set (0.00 sec)
各句の役割と処理の流れ
- GROUP BY CustomerName:顧客名ごとに行をグループ化し、sum()でそれぞれの商品価格の合計を計算します。
- HAVING sum(ProductPrice) BETWEEN 1600 AND 2000:集計後の合計値に対して範囲条件を適用します。合計1200のMikeなど、範囲外のグループは除外されます。
- ORDER BY CustomerName DESC:最終結果を顧客名の降順(D → C の順)に並べ替えます。
なお、SUM()などの集計関数の結果に対する条件を指定できるのはHAVING句だけです。WHERE句はグループ化される前の個々の行に対して評価されるため、集計後の値をフィルタリングする用途には使えない点に注意してください。
まとめ
「GROUP BYで集計 → HAVINGで集計結果を絞り込み → ORDER BYで並べ替え」という流れを1つのクエリにまとめれば、目的のデータを効率的に取得できます。売上集計やレポート作成などで頻繁に登場する定番パターンなので、ぜひマスターしておきましょう。
-
MySQLで特定のレコードを先頭に固定し、残りの行を元の順序のまま表示する方法
MySQLでは、ORDER BY句を工夫して使うことで、特定の条件に一致するレコードを最上位に固定しつつ、それ以外のレコードを元の順序のまま表示できます。この記事では、その具体的な手順をサンプルコードとともに解説します。1. サンプルテーブルの作成まず、テーブルを作成します。mysql> create table DemoTable -> ( -> Id int, -> Name varchar(20) -> ); Query OK, 0 rows affected (0.82 sec)2. レコードの挿入次に、INSERTコマンド
-
MySQLでAND・OR演算子を組み合わせた単一クエリを使って特定のレコードを取得する方法
MySQLでは、AND演算子とOR演算子をWHERE句で組み合わせることで、複数の条件を指定しながら特定のレコードを1つのクエリで取得できます。本記事では、実際にテーブルを作成し、データを挿入して、AND・ORを組み合わせたクエリの動作を確認していきます。 1. テーブルの作成 まず、CREATE TABLE文でサンプル用のテーブルを作成します。 mysql> create table DemoTable2015 -> ( -> StudentId int, -> StudentName varchar(20), -> Stude