はてだBlog(仮称)

私的なブログど真ん中のつもりでしたが、気づけばWebサイト系のアプリケーション開発周りで感じたこと寄りの自分メモなどをつれづれ述べています。2020年6月現在、Elasticsearch、pandas、CMSなどに関する話題が多めです。...ですが、だんだんとより私的なプログラムのスニペット置き場になりつつあります。ブログで述べている内容は所属組織で販売している製品などに関するものではなく、また所属する組織の見解を代表するものではありません。

SQLについて、俗なユーザが思うことつれづれ(シンタックスとか): ひとことでいうとFROM(ON やJOIN含む)、WHERE、GROUP BY、HAVING、SELECT(→ ORDER BY)の順に解釈する

SQLシンタックス(の背景にある考え方)

SQLって関数的なのはスバラシイが、なんかもやもやする。

これはSQLが何をどう扱うかという次のことが分からなかったから。

  • 表(リレーション)の演算、集合の演算
  • FROM(ON やJOIN含む)、WHERE、GROUP BY、HAVING、SELECT(→ ORDER BY)の順に解釈する

参考図書:達人に学ぶ SQL徹底指南書

https://www.amazon.co.jp/dp/4798115169

上記の書籍で、後者にさらっと触れてあるのをみるまで、ずっと分からなかったんだよな〜(もやもやしていたのにヤッパリ分かってなかった)と自覚できた。

Oracleとかで、シータ結合のシンタックスをチラ見したりしてますます分からなくなって、おかげで随分回り道をした気がする。

簡単に分かるSQLみたいなやつでも、いきなりSQLから入るより、ホンの数行でも良いので上記についてふれた方がよかろうと思う。

ところで、SQLに限らず(ただしSQLが一番あてはまりそうに自分では思う)の話だが、この類の「このシンタックスで、データや集合に対する、このような演算を行う」ということ自体を表すちょうど良い用語はあるだろうか。プロシージャ? プロトコル? どちらも、ちょっと違うような気がする。

また、呼び名はともかく、チュートリアルとか、チートシートとか、最速マスターXXみたいなので体に覚えさせるのと併用はするとして、また好きな人・それができる人はBNF記法とかから入っても良いと思うが、この演算をこういう記法やこの関数やAPIでこのように処理できる、というのを書き手読み手双方に手間をかけずに、説明する楽な方法はないだろうか。

まあ、そんなものはあってもなくても、少なくともSQLについては

  • FROM(ON やJOIN含む)、WHERE、GROUP BY、HAVING、SELECT(→ ORDER BY)の順に解釈する

というのは、自分のようなもの分かりの悪い人向けに、口を酸っぱくしてだれか言い続けて欲しい。

(副問い合わせは応用編としておいておくとして、)表を結合した大きな表を作って、条件に当てはまる行を選択して、グループ化するならして、グループ化したものについて、条件があるならさらに絞り込んで...と考えると当たり前なんだけどね。

副問い合わせ(サブクエリ)

どこかで見たのだが、

  • 使い捨てのビュー

だと考えるとスッキリする。

また、

*スカラ・サブクエリ(単一行副問い合わせ)

*複数行が返る副問い合わせ

*相関副問い合わせ

は、順を追って、分けて理解した方が良いような気がする。

その方が、スカラ・サブクエリはほぼSQLのどこにでも配置できる一方、複数行副問い合わせはSELECTのところには配置できず、WHERE句に複数行比較演算子(IN、ANY、ALL)とEXISTSなら配置できることがしっくりくる。*1

相関副問い合わせは曲者。

www.atmarkit.co.jp

... というように、実施する演算がこういうというものだと分からないとシンタックスどおり使いこなせない。 見よう見まねで変なSQLを書いてしまいそうになる。 (引用しておいてケチをつけるわけではないが、もっと相関副問い合わせの演算の本質を表す説明方法が眠っているような気がする。)

結局のところ、「(最年長の社員の年齢ではなく、)最年長の社員のレコードを取り出す」系の用途なら相関副問い合わせ...という理解の方が腹落ちするのかな。

ONには結合条件だけでなく、絞り込みも書ける

ONには結合条件を指定するものだと思い込んでいたが、結合する元のテーブルからあらかじめレコードを絞り込むべき時には、WHERE句に指定するような条件も設定できる。

atsuizo.hatenadiary.jp

今時、性能を考えてというのは無理にしなくて良さそう。 ただ、それを差し引いても、この構文を知らないと、知らずに初めてこの構文を見た時面食らいそう。

正規化のために別テーブルに格納しているものを元のビジネス視点の取引データの集合を表すために結合する場合はWHERE句を使うのが自然なような気がする。逆に、なんらかのデータの発見などのために、そもそも何と何を結合するかという切り口の場合はONで指定するんだろうな。→それぞれの例が欲しいところだが今回は略。

WITH句やCASE式

WITH句はある種のシュガーシンタックスだと思うが、慣れておいた方が良いよね。 やむを得ずSQLを動的に組み立てるようなことをせねばならんアプリとかでもこの構文を知っていると黒魔術度合いが少し緩和される。

CASE式は、上記の書籍を読もう。

WITH句、CASE式ともに、ループ処理を記述せずにちょっとだけSQLに手続き風の考え方を入れ込むことができる*2ので使いこなせるようにしたいところ。

*1:ここでは、というかこのコラムでは性能のことは特に気にしないことにする

*2:※アカデミック的には正確な表現ではないかもしれません