ひよこの外部記憶

めもおきば

「達人に学ぶSQL徹底指南書」ふりかえり

この本読んで思ったことや大事だと思った箇所のメモ
例題や問題とその意図を記載することにより、後から理解しているか、覚えているかを確認する意図で記載していく

www.shoeisha.co.jp

書籍を読んで思ったこと箇条書き

  • この本はSQLの研修を受けて、仕事でも使ってるけどなんか良く分からんみたいな人には結構オススメ
  • WINDOW関数についてそろそろ学ばなきゃ、みたいに思ってる人にもオススメ
  • WINDOW関数は普通のプログラミングの見方を持っていると、他の書き方よりもとっつきやすい
  • さよなら相関サブクエリ、こんにちはWINDOW関数
  • CASE式の強力さに触れられる
  • 集合論からみたSQL, 述語論理からみたSQL
  • 他の言語以上に闇が深いSQLのNULL

1章 CASE式のススメ

所感

  • CASE式すごい
  • SQL自体は見やすくはならないかもしれないが、SQLである程度フォーマットしたりする必要がある時のため覚えておきたい
  • DECODE使う必要はほぼ無い

要約

  • CASEは文ではなく「式」
    • 列名や変数を書ける場所ほぼ全てに書ける
  • 実装非依存かつ高い表現力を持つ

コード体系の変更

  • 選択したい行の形をCASEを用いて表現する
  • SELECT句とGROUP BYに同条件を指定すると実現可能
    • (SQLの範囲で取りたい断面で情報の取得が可能)

1. 行持ちを列持ちに

  • 集約関数の引数にCASE式で条件に当てはまるものだけ対象にする
  • SELECT句に別名をつけて、GROUP BYで使える実装もある
pref_name sex population
徳島 1 60
徳島 2 40
香川 1 100
香川 2 100
・・・ ・・・ ・・・

pref_name
徳島 60 40
香川 100 100
・・・ ・・・ ・・・

2. 表のクロス表作成

  • 以下の2表からクロス表作成
  • CASE式の条件をサブクエリで実現する

CourseMaster

id name
1 SQL入門
2 財務知識
・・・ ・・・

OpenCourses

month id
201806 1
201806 3
201806 4
201807 1
・・・ ・・・

クロス表

コース名 6月 7月 8月
SQL入門
・・・ ・・・ ・・・ ・・・

3.CASE式の中で集約関数

  • 1つのクラブのみに所属している人はHAVING, 複数の場合はmain_clug_flgで選択可能
  • CASE式の中で集約関数を使えば、HAVING句を書かなくても同等の処理が出来る
std_id club_id club_name main_club_flg
100 1 野球 Y
100 2 吹奏楽 N
200 2 吹奏楽 N
200 3 バドミントン Y
200 4 サッカー N
300 4 サッカー N
400 5 水泳 N
500 6 囲碁 N

std_id main_club
100 1
200 3
300 4
400 5
500 6

2章 必ずわかるWINDOW関数

所感

  • 相関サブクエリより読みやすいしパフォーマンスも良い
  • 一部が実行出来るの大きなメリット、仕事でもガンガン使っていきたい
    • 少し古いバージョンのPostgresql使っていると機能足りなかったりする
    • mysqlは対応が遅いため、なにか足りなかったりすることが多い(らしい)

要約

  • 主要なRDBMSがWINDOW関数を実装した
  • WINDOW関数の機能は以下のように説明出来る
    • PARTITION BY句は集約しないGROUP BY、レコード集合のカット
    • ORDER BY句によるソート
    • フレーム句によるレコードを中心としたサブセット定義

3章 自己結合の使い方

所感

  • 集合を作るために自己結合を活用する、という観点は興味深い

要約

  • マスタの組み合わせを得たい時など、重複順列、順列、組み合わせを自己結合で実現出来る
  • 重複の排除(DELETE文の利用)も自己結合を上手く使うと実現可能
    • rowid使って1つだけ残すような感じ
  • 自己結合を非等値結合と組み合わせて使う
    • 部分的に不一致なものを取得する
    • 同じ値段のもの(=名前が違うもの)みたいな感じで取れる
  • GROUP BYと組み合わせると再帰的集合を作ることが出来る

4章 3値論理とNULL

所感

  • 第一版を読んだ時に最も印象に残った章
  • unknownという地獄
  • NULLは使わないようにしたい、と思うけどまぁどうでも良いところには使ってしまう
  • NOT NULL制約は付けられる場合には付与すべきと思わされる

要約

  • NOT INとNOT EXISTSでは同値変換出来ない

    • NULLが入ると、NOT INは条件がunknownになる
    • EXISTSはtrueかfalseかのどちらかしか返さない
  • 極値関数を使うと、NULLが入っていてもうまく無視してくれる

    • MAXに (1 ,3 , NULL)と入ってきたら3が返る
    • 空集合が渡された時には極値関数の結果はNULLになる

5章 EXISTS述語の使い方

所感

  • 2回目読んだ中で一番印象的な章の一つ
  • この章、SQL本として有用なのはもちろんだが読み物としても面白い
  • 全称量化に気づくのがまずムズイ

要約

  • データベースにおける行はデータでなく命題
  • 述語とは戻り値が真理値になる関数
  • EXISTSは二階の述語
  • データが無い行、というような条件を探す場合には、理想的な状態(=全部入りの状態)をCROSS JOIN等 で作成し、そこからNOT EXISTSなり、EXCEPTなりで絞り込む
  • 全称量化「全ての行について〜」を「〜でない行が1行も存在しない」に置き換える
  • 列方向への全称量化、存在量化は対応する関数がある

テストの点数条件絞り込み

std_id subject score
100 算数 100
100 国語 80
100 理科 80
200 算数 80
200 国語 95
300 算数 40
300 国語 90
・・・ ・・・ ・・・
  • 全ての科目が50点以上の生徒を抽出
    • DISTINCTしない結果を考える、id300の国語は何故出力されないのか
  • 数学が80点以上、国語が50点以上の生徒を抽出
  • どちらも点数がある場合のみを条件に

6章 HAVING句の力

HAVING句は集合指向言語の観点から見ると強力
count()とcount(col_1)の結果は異なる
col_1にNULLが入って居た場合にはカウントされないが
の場合は例え1列しかなくてもカウントされる

GROUPに1種類しか存在しない、を表現する場合には以下の3種類の方法がある

1. NOT EXISTSで書く
2. HAVINGで特性関数のようなものと個数を比較する
3. HAVINGで評価したい値のMAXとMINが一致する

GROUP内に重複が無いもの、を表現する場合には対象列の個数と対象列をDISTINCTした結果が一致するかを比較する

バスケット解析 item | item | |:-------| |ビール| |紙おむつ| |自転車| |・・・|

ShopItem | std_id | subject | |:-----------|:------------:| |仙台|ビール| |仙台|紙おむつ| |仙台|自転車| |仙台|カーテン| |東京|ビール| |東京|紙おむつ| |東京|自転車| |大阪|テレビ| |大阪|紙おむつ| |大阪|自転車|

  1. Itemに含まれるものを全て取り扱っている店舗を取得
  2. 取り扱っているものが過不足なくItemの項目と一致する店舗を取得