はじめに
HAVING句でデータの歯抜けを探す方法を見ながら、集合思考言語と手続き型言語の違いを考えてみます。
Schema (MySQL v8.0)
CREATE TABLE members (
id INT NOT NULL PRIMARY KEY auto_increment,
name TEXT
);
INSERT INTO members VALUES
(1, 'brown'),
(2, 'rally'),
(3, 'boggie'),
(5, 'tashiro'),
(6, 'yamada'),
(8, 'takeda');
Result
id | name |
---|---|
1 | brown |
2 | rally |
3 | boggie |
5 | tashiro |
6 | yamada |
8 | takeda |
このデータの歯抜けをどう探しますか?
仮に、このテーブルがファイルで、手続き型言語を使って調べるなら...
- ソートする
- ソート順にループさせて、1行づつ次の行と比較
ファイルのレコードは順序を持ち、それを扱うためのプログラミング言語もソートを行えます。
一方、テーブルの行は順序を持ちませんし、SQLもソートの演算子を持っていません。
ORDER BY 句はSQLの演算子ではなくカーソル定義の一部です。
ORDER BY は、結果を表示する目的には便利だが、それ自体はリレーショナル演算子ではない。
引用👇(15のページに記載)
SQLではどう表現するか
複数行を1つにまとめて集合として扱います。
query
SELECT '歯抜けあり' AS gap
FROM members
HAVING COUNT(*) <> MAX(id)
<>
は、jsでいう!==
で、等しくないという意味です。
results
gap |
---|
歯抜けあり |
このクエリは、1行返れば「歯抜けあり」が返るが何も返らなければ連番であるということになります。
図解するとこういう感じです。
つまり、一方の集合は他方の写像であることをテストしていることになります。
上記のクエリは、歯抜けが存在する場合、絶対不一致になりますね。
HAVINGはGROUP BY と併用しなければいけないわけでは無い
現在の標準SQLでは、HAVING句を単独で使えるそうです。
ただし、SELECT句で元テーブルの列を参照できなくなるので、上記SQLのように、定数を返すようにするか、以下のように集約関数を使う必要があります。
SELECT SUM(*) FROM ...
本日は、以上です。
参照
105 - 109p
アウトプット100本ノック実施中