【SQL】集約キー:GROUP BY句に書くもの
集約キーとは
GROUP BY句に書いた列名のこと- 集約キーは複数指定できる
集約キーがひとつ
/* 集約キー:shohin_bunrui */
SELECT shohin_bunrui, COUNT(*)
FROM Shohin
GROUP BY shohin_bunrui;
shohin_bunrui | count
---------------+-------
キッチン用品 | 4
衣服 | 2
事務用品 | 2
/* 集約キー:torokubi */
SELECT torokubi, COUNT(*)
FROM Shohin
GROUP BY torokubi;
torokubi | count
------------+-------
| 1
2009-11-11 | 1
2009-09-20 | 3
2009-09-11 | 1
2009-01-15 | 1
2008-04-28 | 1
集約キーがふたつ
/* 集約キー:shohin_bunrui, torokubi */
SELECT shohin_bunrui, torokubi, COUNT(*)
FROM Shohin
GROUP BY shohin_bunrui, torokubi;
shohin_bunrui | torokubi | count
---------------+------------+-------
衣服 | | 1
キッチン用品 | 2009-01-15 | 1
衣服 | 2009-09-20 | 1
キッチン用品 | 2008-04-28 | 1
事務用品 | 2009-11-11 | 1
事務用品 | 2009-09-11 | 1
キッチン用品 | 2009-09-20 | 2
集約キーがみっつ
/* 集約キー:shohin_mei, shohin_bunrui, torokubi */
SELECT shohin_mei, shohin_bunrui, torokubi, COUNT(*)
FROM Shohin
GROUP BY shohin_mei, shohin_bunrui, torokubi;
shohin_mei | shohin_bunrui | torokubi | count
----------------+---------------+------------+-------
フォーク | キッチン用品 | 2009-09-20 | 1
包丁 | キッチン用品 | 2009-09-20 | 1
圧力鍋 | キッチン用品 | 2009-01-15 | 1
穴あけパンチ | 事務用品 | 2009-09-11 | 1
カッターシャツ | 衣服 | | 1
ボールペン | 事務用品 | 2009-11-11 | 1
おろしがね | キッチン用品 | 2008-04-28 | 1
Tシャツ | 衣服 | 2009-09-20 | 1
- 集約キーが増える
- グループが細分化されてくる
- 重複しない列が集約キーに含まれると、集約(グループ化)の意味はなくなる
- すべての列を集約キーにすると、集約(グループ化)の意味はなくなる
SELECT句に集約キーを書かなくても動く
ただ、書かないと何で集約したか表示されないので読みにくすぎる
/* SELECT句に集約キーを書かない */
SELECT COUNT(*)
FROM Shohin
GROUP BY shohin_mei, shohin_bunrui, torokubi;
count
-------
1
1
1
1
1
1
1
1
-- ****************
SELECT COUNT(*)
FROM Shohin
GROUP BY torokubi;
count
-------
1
1
3
1
1
1
-- ****************
SELECT COUNT(*)
FROM Shohin
GROUP BY shohin_bunrui;
count
-------
4
2
2
【注意】ASで付けた別名は集約キーにならない
- 別名はあくまで「表示用の呼び名」
- 集約キーになるのは元の列
- 別名が元の列名と被ると、元の列として解釈される
(意図と違うグループ化がされてしまううえに、気づきにくい事故が起きる)
前提:PostgreSQLの場合
GROUP BYに書かれた名前は、まず本物の列名として探す- なければ別名として扱う
【検証①】別名に実在する列名をつける
/* ①shiire_tanka, hanbai_tanka が実在するか確認 */
SELECT shiire_tanka, hanbai_tanka
FROM Shohin;
/* 実在する列名だった */
shiire_tanka | hanbai_tanka
--------------+--------------
500 | 1000
320 | 500
2800 | 4000
2800 | 3000
5000 | 6800
| 500
790 | 880
| 100
/* ②「shiire_tanka」に「hanbai_tanka」と別名をつける
集約キーは「hanbai_tanka」(shiire_tankaの別名)とする */
SELECT shiire_tanka AS hanbai_tanka, COUNT(*)
FROM Shohin
GROUP BY hanbai_tanka;
/* 実行するとエラーが発生 */
ERROR: column "shohin.shiire_tanka" must appear in the GROUP BY clause or be used in an aggregate function
/* エラー内容
列 "shohin.shiire_tanka" は、`GROUP BY`句に書かれているか、
集約関数の中で使われているかの、どちらかでなければなりません
前提①に基づき、本物の列として扱ったためエラーとなった */
【検証②】別名が実在する列名とかぶらない
注意:PostgreSQLでは通るが、他のDBMSではエラーになる可能性がある
SELECT shiire_tanka AS "仕入単価", COUNT(*)
FROM Shohin
GROUP BY 仕入単価;
/* 前提②に基づき、「仕入単価」を別名として扱った */
仕入単価 | count
----------+-------
| 2
320 | 1
500 | 1
2800 | 2
5000 | 1
790 | 1
【結論】集約キーに別名を使わない
- 別名の文字列を変えただけで、エラーが出たり出なかったりする
- DBMSによって結果が異なる
- 結果の正確さが担保できない
参考書籍:ミック『SQL 第2版 ゼロからはじめるデータベース操作』(翔泳社)