今日はSQLZOOでSQLを学んだ。
普段使ってるDBで試し打ち。
開発環境
$ docker exec -it faaaar-db bash root@{CONTAINER_ID}:/# psql -U postgres postgres=# \dt List of relations Schema | Name | Type | Owner --------+-----------+-------+---------- public | idol | table | postgres public | idol_unit | table | postgres public | unit | table | postgres
BETWEEN: 基本形
ageが20から25までのレコードを抽出。
SELECT * FROM idol WHERE age BETWEEN 20 AND 25 ;
↓
id | name | age | height | birth_place | birth_day | blood_type ----+-------------+-----+--------+-------------+-----------+------------ 9 | 桑山 千雪 | 23 | 163 | 山口県 | 4/18 | A 16 | 有栖川 夏葉 | 20 | 168 | 愛知県 | 8/16 | B 25 | 緋田 美琴 | 24 | 170 | 北海道 | 9/8 | B 26 | 斑鳩 ルカ | 20 | 161 | 神奈川県 | 1/31 | A
BETWEENは範囲がある概念に対してならある程度は使えそう?
BETWEEN: 応用形
所属ユニット数が2から3までのアイドルを列挙したい。
ステップ1
まずアイドルと所属ユニットを紐付ける。
アイドルとユニットの情報は別のテーブルに存在するため結合させる。
SELECT i.id as id, i.name as name, u.name as unit FROM idol i INNER JOIN idol_unit iu ON i.id = iu.idol INNER JOIN unit u ON iu.unit = u.id ;
↓
id | name | unit ----+-------------+-------------------------------- 1 | 櫻木 真乃 | Stella 1 | 櫻木 真乃 | イルミネーションスターズ 2 | 八宮 めぐる | Sol 2 | 八宮 めぐる | イルミネーションスターズ 3 | 風野 灯織 | Luna (省略)
ステップ2
所属ユニットが2から3までのアイドルを列挙するには、アイドルの所属ユニット数を知る必要がある。
idの重複数をカウントすれば目的が叶えられそう。
(nameでも現状はいけそうだが、同姓同名を考えるとユニークなIDで行うのが安牌)
SELECT idl.id AS id, idl.name AS name, COUNT(idl.id) FROM idol idl INNER JOIN idol_unit idlunt ON idl.id = idlunt.idol INNER JOIN unit unt ON idlunt.unit = unt.id GROUP BY idl.id ;
↓
id | name | count ----+-------------+------- 12 | 小宮 果穂 | 2 24 | 七草 にちか | 1 19 | 和泉 愛依 | 2 25 | 緋田 美琴 | 1 21 | 樋口 円香 | 2 (省略)
ステップ3
ステップ2に対してBETWEENを指定すれば良さそう。
SELECT idl.id AS id, idl.name AS name, COUNT(idl.id) AS count FROM idol idl INNER JOIN idol_unit idlunt ON idl.id = idlunt.idol INNER JOIN unit unt ON idlunt.unit = unt.id GROUP BY idl.id HAVING idl.count BETWEEN 2 AND 3 ;
↓
id | name | count ----+-------------+------- 4 | 月岡 恋鐘 | 2 10 | 大崎 甜花 | 2 9 | 桑山 千雪 | 2 7 | 白瀬 咲耶 | 2 15 | 西城 樹里 | 2 (省略)
手元の実行結果では2から3までで絞れているのだが、ブログに載せるには量が多いので整形する。
ステップ4
countカラムを降順で表示。
SELECT idl.id AS id, idl.name AS name, COUNT(idl.id) AS count FROM idol idl INNER JOIN idol_unit idlunt ON idl.id = idlunt.idol INNER JOIN unit unt ON idlunt.unit = unt.id GROUP BY idl.id HAVING idl.count BETWEEN 2 AND 3 ORDER BY idl.count DESC ;
↓
id | name | count ----+-------------+------- 20 | 浅倉 透 | 3 17 | 黛 冬優子 | 3 16 | 有栖川 夏葉 | 3 7 | 白瀬 咲耶 | 2 15 | 西城 樹里 | 2 (省略)
結構思い通りに書けた。
試行錯誤しながらやっているので一度体系的に学んだ方が良さそう。