エンジニアもどきの雑記

メモ帳です。きっと。macアプリ配信windowsでもできるようになるまで絶対にメイン機にしないマン。特筆しない限り環境は【win10home,i5-7200u,8g,64bit,巨乳が好き】

MysqlでGROUP BYの後に条件つけたい時のHAVING



久々の技術記事な気がする。
いや、技術ってほどの内容もないんだけど。

一応サーバー担当なのであれやこれやと平日八時間は触る。
家では全然ウェブやらサーバーやらは触らないんだけど。

で、今日のはクエリ。

とりあえずテスト用に作成から

mysql> create database mysql_test
mysql> use mysql_test

mysql> create table test_table (
    -> id int(11),
    -> name varchar(20),
    -> subid int(11)
    -> );
Query OK, 0 rows affected (0.29 sec)


で、とりあえずデータ入れる。

入れたらこう。

mysql> select * from test_table;
+------+---------+-------+
| id   | name    | subid |
+------+---------+-------+
|    1 | test    |     5 |
|    2 | i       |     5 |
|    3 | love    |     6 |
|    4 | boobies |     6 |
|    5 | hoge    |     9 |
|    6 | fuga    |    10 |
+------+---------+-------+
6 rows in set (0.00 sec)


これをとりあえず普通にGROUP BUする
subidで

mysql> select subid from test_table group by subid;
+-------+
| subid |
+-------+
|     5 |
|     6 |
|     9 |
|    10 |
+-------+
4 rows in set (0.00 sec)


まぁ当然こうなる
。 今気づいたけどちょっと例がわるい。
が、このまま進める


で、HAVING

mysql>  select subid from test_table group by subid having subid > 5;
+-------+
| subid |
+-------+
|     6 |
|     9 |
|    10 |
+-------+
3 rows in set (0.00 sec)


こんな感じでgroup byした結果からさらに条件を付けることができる。
例がわかりにくくてごめんよ。
計画性のなさが滲み出てきてる。

で、見てわかるとおり、それって

mysql> select subid from test_table where subid > 5 group by subid;
+-------+
| subid |
+-------+
|     6 |
|     9 |
|    10 |
+-------+
3 rows in set (0.00 sec)


じゃね?
ってなるよね。
うん、わかる。

まぁでもこうやって用意されている以上まったく同じなんてことはなくて、
単純に評価順が違う。

where→group by→having

で評価されるらしいので、
whereの場合は以下

mysql> select subid from test_table where subid > 5;
+-------+
| subid |
+-------+
|     6 |
|     6 |
|     9 |
|    10 |
+-------+
4 rows in set (0.00 sec)

subidが5より上のものをとってから、
group byして集計。


そしてhavingだと

mysql> select subid from test_table group by subid;
+-------+
| subid |
+-------+
|     5 |
|     6 |
|     9 |
|    10 |
+-------+
4 rows in set (0.00 sec)

group化してから、条件で抽出。


当然使いどころとかはある。
というか今日仕事してて既存のクエリ改造で必要になったから調べた。

が、使わわなかった。

上記tableでいうと、
subid 5に対して1と2のidがあると思うんだけど、1で全体検索した上でnameとsubidと、1ではないidを取得したかった。
id=1はフロントからjsonでparamとして渡されてくる。

そうすると以下

mysql> select * from test_table where id = 1;
+------+------+-------+
| id   | name | subid |
+------+------+-------+
|    1 | test |     5 |
+------+------+-------+
1 row in set (0.00 sec)


まぁまずこうなってた。
1ってidは来ているけど、それだけで拾うとid1のデータが取れる。当然。
でもこの結果で得た5で紐づくid1じゃないidが欲しい。

サブクエリも、joinも重いんですよ。
こんな簡易なtableじゃないし、量も何万桁だし。
って、いろいろやっている途中でhavingに出会って調べた。

故の今日の記事。

ちなみに上記問題は、別に重要な箇所でもないので、
クエリを分けることになりましたとさ。

ういうい。

mysqlなんて日常的に使いすぎて当たり前のようにいろいろ打つけど、
まだまだ知らない機能がたくさんあるんだなぁ、って感じでした。