MySQL
SQL
初心者

初めてのSQL(Learning SQL)を読んだまとめ 1

はじめに

独習PHPが終わったので次はSQL。ついでに初オライリー。

今まで

毎日就業前に一時間程度技術書を読み、読み終えてから付箋貼っておいたところを見返してまとめる

これから

毎日就業前に一時間程度技術書を読み、その日の夜に前日読んだ部分をまとめる

気づき

この方法であれば多少内容が薄くても毎週投稿は叶うはずだし、忘却曲線的にも理に適っているはず…!

あと本のとおりにやってるのに、うまくいかない…っていう時が一番学習になっている気がする

まとめ

非リレーショナルデータベース

最近はNoSQLとも呼ばれているらしい。
すごく綺麗にまとめているところがあったので参照

要するに、RDBMSではトランザクション管理のためにデータをストレージを共有する必要があるため、スケールアウトが難しいこと、柔軟さの代償として複雑な処理を与えてしまいがちなことから、パフォーマンス的に新しい物を求める動きが出てきたということでしょうか。

RDBMSの起源は1970年のIBM研究所から発表された論文、Oracleの発売から考えても40年以上が経過しているわけで、備えあれば嬉しいなの精神で

制約(CONSTRAINT)

PRIMARY_KEYやNOT_NULLみたいに、カラムに格納する値に制限をつけておくことができる

ちょっと大変だなと思ったのはFOREIGN_KEYで、

CREATE TABLE favorite_food
(person_id SMALLINT UNSIGNED,
food VARCHAR(20),
CONSTRAINT pk_favorite_food PRIMARY_KEY (person_id, food),
CONSTRAINT fk_person_id FOREGINKEY (person_id)
REFERENCES person (person_id)
)

FOREIGNKEY (列) REFERENCES 親テーブル(列)で指定して、親テーブルの列に存在しない値が子テーブルの列に格納されないようになるんだけども、これをしてしまうと親テーブルの列が削除できなくなったりして意外と面倒だった。

ちなみに普通のshow columns from hogedesc hogeでは制約は見られないのでshow create table hogeを使う。削除や付加にはいつも通りalter table
使うんだけれどもね

列エイリアス

SELECT COUNT(hoge) AS fugaみたいに書けばカラム名を変えられるのは知っていたけれども、ASを抜いてSELECT COUNT(hoge) fugaでも大丈夫なのは知らなかった。

式の評価順序

いいまとめがあったので詳しくはこちらを見ていただくとして、参考になったのはこの2点
1. LIMITは最後に評価されるので書いたからといってクエリは早くならない(描画とかはまた別問題)
1. SELECTに列エイリアスを書いてもwhereではそのエイリアスを使えない。

結果セットを早い段階で小さくしておくのがコツらしい。

一番最初に全部入りのでかいテーブル(FROM, JOIN)を作っておいて、条件で絞り込んで(WHERE)、まとめて(GROUP BY)、必要そうなものだけ取り出す(SELECT, LIMIT)ってイメージしておくだけで全然違う気がする

ビュー

普通のテーブルは正規化しておかないとデータが冗長になるので、単体で使えるテーブルにはなりにくい。そこで予めサブクエリとしてよく使うもの(SELECT文で取れる結果セット)を登録しておいて、1つのテーブルとして扱うことでクエリを簡潔にすることができる、ということらしい。

便利そう。実際にLaravelでビューを使って任意のSQLを書く方法もあるみたいだし、使ってみたい…!

ORDER BYの式による並び替え

たとえば会員番号(例:1234-111-567)の下3桁で並び替えたい、みたいなときは

SELECT *
FROM cutomers
ORDER BY RIGHT(cust_id, 3);

みたいに書ける。

全然関係ないけど何でSQLの教本ってWeb系フレームワークの規約に多少なりとも沿った形では書いてくれないんでしょうね。

between演算子

2000年生まれの人が欲しい時

SELECT *
FROM users
WHERE birth_date >= '2000-01-01' AND birth_date <= '2000-12-31';

みたいに書きがちなんだけどbetween演算子を使えば

SELECT *
FROM users
WHERE birth_date BETWEEN '2000-01-01' AND '2000-12-31' ;

って書けて多少楽なんだよということ。気をつけなければいけないのはANDの左が下限で右が上限だということと、指定した値が含まれること。

照合順序

utf8_general_ciとかutf8_unicode_ciのこと

名前からして日本語などの非アルファベット文字のソート順とかを決めてるのかなーとか思ってたんだけど、それだけにとどまらない様子

詳しくはこちらなどを見ていただきたいのだが、要するに

文字列の比較に使われるので、フィルタ(WHERE句とかJOINの結合条件とか)のかかり方に影響が出るほか、速度にも違いが生じるとのこと

ちなみに照合順序が違うカラムを結合するとエラーが出る(回避はできる)ので、普段は硬めのutf8_general_ciを使っておいて、あいまい検索したい時だけcollate utf8_unicode_ciみたいに指定してあげるのが良さそうですね

USING

SELECT e.fname, e.lname, d.name
FROM employee e INNER JOIN department d
USING (dept_id)

2つのテーブルの結合に使用する列の名前が同じであるときはONキーワードの代わりにUSINGを使って簡単に書くことが出来るというもの。

そういう規約や設計をしておいて、すべてのテーブルがそういう結合の仕方が出来るようになってれば便利かな?ぐらい。Webフレームワークの中では出番は少なそうだなぁ。