📘

SQLのGroupBYの挙動について考える。

に公開

まえがき

SQLで集計する場合、GroupByを使うことが多いと思いますが、この挙動を把握していなくてハマったことがありました。
あるカラムに入っている値の一覧を重複なしで取り出して、それを画面に出そうとしているのに、どうしても重複が解消できないことがありました。
これについて解説していきます。

解説

テストデータとして以下を用意しました。

CREATE TABLE public.customer (
	id serial4 NOT NULL,
	"name" varchar NULL,
	gender bpchar(1) NULL,
	age int4 NULL
);
INSERT INTO public.customer
(id, "name", gender, age)
VALUES(nextval('customer_id_seq'::regclass), 'Lloyd', 'M', 17)
,(nextval('customer_id_seq'::regclass), 'Collet ', 'F', 16)
,(nextval('customer_id_seq'::regclass), 'Genius ', 'M', 12)
,(nextval('customer_id_seq'::regclass), 'Refill ', 'F', 23)
,(nextval('customer_id_seq'::regclass), 'Shihna ', 'F', 19)
,(nextval('customer_id_seq'::regclass), 'Zelos ', 'M', 22)
,(nextval('customer_id_seq'::regclass), 'Presea  ', 'F', 12)
,(nextval('customer_id_seq'::regclass), 'Regal  ', 'M', 33)
,(nextval('customer_id_seq'::regclass), 'Kratos   ', 'M', 28)
;

そうするとこういう原本ができます。

SELECT c.* FROM public.customer AS c

id|name     |gender|age|
--+---------+------+---+
 1|Lloyd    |M     | 17|
 2|Collet   |F     | 16|
 3|Genius   |M     | 12|
 4|Refill   |F     | 23|
 5|Shihna   |F     | 19|
 6|Zelos    |M     | 22|
 7|Presea   |F     | 12|
 8|Regal    |M     | 33|
 9|Kratos   |M     | 28|

ここから、このテーブルに入っている年齢の一覧を取得したいと思います。
なので、年齢でグルピーングしてみます。

SELECT age
FROM public.customer
GROUP BY age
ORDER BY age ASC
;

age|
---+
 12|
 16|
 17|
 19|
 22|
 23|
 28|
 33|

問題ないですね。
年齢の一覧が重複なくとれています。

今度は年齢も集計条件に加えてみます。

SELECT age
FROM public.customer
GROUP BY age,gender
ORDER BY age ASC
;

age|
---+
 12|
 12|
 16|
 17|
 19|
 22|
 23|
 28|
 33|

あれ!?「12」が二つある??
という具合です。

これは取得する列を増やせば明白なのですが、

SELECT age,gender,count(*)
FROM public.customer
GROUP BY age,gender
ORDER BY age ASC
;

age|gender|count|
---+------+-----+
 12|M     |    1|
 12|F     |    1|
 16|F     |    1|
 17|M     |    1|
 19|F     |    1|
 22|M     |    1|
 23|F     |    1|
 28|M     |    1|
 33|M     |    1|

こうなってるわけです。
12歳の男性が1人、12歳の女性が1人、というレコードに分かれたから2行になってたんですね。

終わりに

今回は単純な取得なので確認しやすくしていますが、実際に私がハマっていたときは、この結果をサブクエリとしてメインクエリのIN句に使ったりとかだったので、大変でした。
分かってしまえば当たり前ですが、グルーピングの条件を詳細にしていけばレコード数は増えます。
エクスプローラでフォルダの中を整理してサブフォルダつくっていうと、フォルダ総数は増えるのとにているかもしれません。

株式会社ONE WEDGE

【Serverlessで世の中をもっと楽しく】 ONE WEDGEはServerlessシステム開発を中核技術としてWeb系システム開発、AWS/GCPを利用した業務システム・サービス開発、PWAを用いたモバイル開発、Alexaスキル開発など、元気と技術力を武器にお客様に真摯に向き合う価値創造企業です。
https://onewedge.co.jp

Discussion