データベース操作を基礎からしっかりと身に付けたいと思ったので手に取った書籍です。
対象
データベース初心者や非エンジニア。
第0章 イントロダクション
書籍では windows 用の設定だけだったので mac 用にqiita記事を参考にしました。
https://qiita.com/ipepi/items/58dedbc0434fa9ea3b71
第1章 データベースとSQL
- データベースとはそもそも何のために使われるのか
- 表計算ソフトとどう違うのか
- 種類と具体例
- SQLとは何か
実際にSQLを書いてみる
create database
create table
drop table
alter table
練習問題でサクッとdrop table
させるところが面白いなと思いました。練習問題ながら、サクッとテーブルを削除するとどうなるのか身をもって辛さを体験できます。
第2章 検索の基本
select
as
でわかりやすい名前で出力するfrom
なしで出力することもできる- 中身が何でもいいとき
'商品' as mojiretsu
で定数を出力するselect distinct
で重複を省くwhere
で絞り込む- 必ず
from
の直後に書く
- 必ず
--
や/* */
でコメントを書くselect
文中で計算もできるNULL
が入るときに気をつける
- 文字列型の順序の原則は辞書式
- 数値の大小とは違う
NULL
を判別するにはis null
やis not null
を使うand
、or
- ベン図は便利
or
よりand
の方が優先される()
で調整する
NULL
は不明(UNKNOWN)
となる- SQLだけは3値論理となる
NOT NULL制約
で対策
- SQLだけは3値論理となる
第3章 集約と並べ替え
集約関数とは
count
- 列名を引数にすると
NULL
を除外した数になる- count関数だけの特徴
- 列名を引数にすると
sum
avg
max
とmin
- どんなデータ型の列にも適用できる
集約関数は最初に
NULL
を除外するcount
だけは例外
重複値を除きたいときは
distinct
()
の中に書くselect count(distinct shohin_bunrui) from shohin;
- 集計関数ならどれにでも使える
group by
- ケーキのように切り分ける
- 商品分類ごとなど
- 必ず
from
の後ろにおく NULL
は1つのグループとなるwhere
も一緒に使えるwhere
で先に絞られたレコードから集約される
- ケーキのように切り分ける
よくある間違い
select
に集約キー以外の列名を書く- 1行でグループ化したなら結果も1行になる
- 書けるもの
- 定数
- 集約関数
group by
で指定した列名
group by
してるときにas
を使う- SQL内部では
group by
がselect
より先になる- 別名を知らない
- SQL内部では
group by
はソートしてくれる?- してくれない
where
にcount
などを書く- 集約関数が書けるのは
select
、having
、order by
だけ
- 集約関数が書けるのは
having
group by
でグループ分けし、さらに条件を指定して絞りこむgroup by
の後ろに書く- 一度集約が終わった段階のテーブルを出発点にしている
- 行に対する条件は
where
で書いた方がいいwhere shohin_bunrui = '衣服'
where
で絞り込んでからソートした方が速いwhere
はインデックスが使える
order by
select
の最後に書く- 同順位のデータの並び順を決定するには
- 複数のソートキーを指定する
NULL
はまとめられるas
を使えるorder by
はselect
より後で実行されるから
- 列番号は使ってはいけない
第4章 データの更新
insert
default
値は明示的な方が良い
insert …… select
でデータをコピーできる- バックアップに使える
insert
内のselect
ではどんなSQL文でも使える
drop table
delete
delete from shohin;
- 使えるのは
where
だけ
update
- 列を
NULL
で更新するNULLクリア
- 複数更新は
set
列を増やす
- 列を
transaction
- ワンセットで行われるべき更新の集合
SQL Server
、PostgreSQL
ではbegin transaction
MySQL
ではstart transaction
Oracle
、DB2
では- ない
- 接続時点でトランザクションが始まっているから
- ない
commit
- ファイルでいうところの上書き保存
rollback
- 保存せずに終了
- ACID特性
- 原子性(Atomicity)
- オール・オア・ナッシング
commit
されるかrollback
されるかどちらかしかない
- オール・オア・ナッシング
- 一貫性(Consistency)
- 制約違反はエラーになってロールバックされる
NOT NULL制約
- 整合性
- 制約違反はエラーになってロールバックされる
- 独立性(Isolation)
- トランザクション同士は独立している
- 永続性(Durability)
- 復旧手段がある
- 実行ログ
- 復旧手段がある
- 原子性(Atomicity)
第5章 複雑な問い合わせ
- ビュー
- 実際のデータを保存していないテーブル
- 保存領域の容量節約できる
- 使い回しが効く
- よく使う
select
をビューにして使いまわす
- 実際のデータを保存していないテーブル
create view
as
を省略しないorder by
は使わない
- サブクエリ
- 使い捨てのビュー
- ビュー定義の
select
をfrom
に持ち込んだもの
- ビュー定義の
- 使い捨てのビュー
- スカラ・サブクエリ
- 必ず1行1列だけの戻り値を返すサブクエリ
- 単一の値が書ける所にはどこでも書ける
- 集約関数を
where
に書けないため重宝する
- 集約関数を
- 絶対にサブクエリが複数行を返さないようにする
SELECTshohin_id,shohin_mei,hanbai_tankaFROMShohinWHEREhanbai_tanka>(SELECTAVG(hanbai_tanka)FROMShohin);
- 相関サブクエリ
- 小分けにしたグループ内で比較する
where
で使う戻り値が複数- 対応する列ごとに比較したいときに使う
- 縛る、制限すると呼ばれる
- 「商品分類で縛って」
- 結合条件は必ずサブクエリの中に書く
- 相関名のスコープ
S2
は消える
- 相関名のスコープ
--SQL Server、DB2、PostgreSQL、MySQLSELECTshohin_bunrui,shohin_mei,hanbai_tankaFROMShohinASS1WHEREhanbai_tanka>(SELECTAVG(hanbai_tanka)FROMShohinASS2WHERES1.shohin_bunrui=S2.shohin_bunruiGROUPBYshohin_bunrui);
第6章 関数、述語、CASE文
算術関数
abs
- 絶対値
mod
- 剰余
- SQL SERVER では使えない
round
- 四捨五入
文字列関数
||
- 連結
- SQL Server と MySQL では使えない
- MySQ は
concat
を使う
length
- 文字列長
- SQL Server では使えない
- DBMS によっては1文字を長さ2以上と数えるLENGTH関数もある
lower
- 小文字化
replace
- 置き換え
substring
- 文字列の切り出し
- 利用できるのは PostgreSQL と MySQL だけ
upper
- 大文字化
日付関数
current_date
- 実行した日付が出力される
current_time
current_timestamp
- 主要DBMS全てで使える
extract
- 日付要素の抜き出し
変数関数
cast
- 型変換
coalesce
NULL
を変換して使いたいときに使用する
SELECTCOALESCE(TS.tenpo_id,'不明')AStenpo_id,COALESCE(TS.tenpo_mei,'不明')AStenpo_mei,S.shohin_id,S.shohin_mei,S.hanbai_tankaFROMTenpoShohinTSRIGHTOUTERJOINShohinSONTS.shohin_id=S.shohin_idORDERBYtenpo_id;
述語
like
- 部分一致
between
- 範囲検索
is null
とis not null
in
とnot in
in
の引数にはサブクエリが使えるin
の中にnull
を入れると常に空っぽになってしまう- 戻り値にも
null
が含まれないように気をつける
- 戻り値にも
--「大阪店に置いてある商品の販売単価」を求めるSELECTshohin_mei,hanbai_tankaFROMShohinWHEREshohin_idIN(SELECTshohin_idFROMTenpoShohinWHEREtenpo_id='000C');
exists
- ある条件に合致するレコードがあるかどうか
true
、false
- 引数は常にサブクエリ
select *
と書く- 合致するかどうかだけなので列名は気にしない
- ある条件に合致するレコードがあるかどうか
--EXISTSで「大阪店に置いてある商品の販売単価」を求めるSELECTshohin_mei,hanbai_tankaFROMShohinASSWHEREEXISTS(SELECT*FROMTenpoShohinASTSWHERETS.tenpo_id='000C'ANDTS.shohin_id=S.shohin_id);
case
式
case
else
は省略しない- 式を書ける場所ならどこでも書ける
select
を柔軟に組み替えられる
--商品分類ごとに販売単価を合計した結果を行列変換するSELECTSUM(CASEWHENshohin_bunrui='衣服'THENhanbai_tankaELSE0END)ASsum_tanka_ihuku,SUM(CASEWHENshohin_bunrui='キッチン用品'THENhanbai_tankaELSE0END)ASsum_tanka_kitchen,SUM(CASEWHENshohin_bunrui='事務用品'THENhanbai_tankaELSE0END)ASsum_tanka_jimuFROMShohin;
第7章 集合演算
- 集合演算の注意事項
- 演算対象のレコードの列数は同じであること
- 足し算の対象となるレコードの列のデータ型が一致していること
select
はどんなものを指定してもいい。だがorder by
は最後に1つだけ
テーブルの足し算と引き算
union
- 和集合
union all
- 重複行を排除しない
intersect
- 共通するレコードを選択する
except
- 引いた残りが選択される
- どちらから引くかで結果が異なる
結合
- 結合とは
- 別テーブルから列を持ってきて増やす
where
などで絞り込むこともできる
- 別テーブルから列を持ってきて増やす
inner join
from
に複数のテーブルを書くon
の後に結合キーを指定するselect
ではTS.tenpo_id
などのように書く
--SQL Server、DB2、PostgreSQL、MySQLSELECTTS.tenpo_id,TS.tenpo_mei,TS.shohin_id,S.shohin_mei,S.hanbai_tankaFROMTenpoShohinASTSINNERJOINShohinASSONTS.shohin_id=S.shohin_idORDERBYtenpo_id;
outer join
- 片方のテーブルの情報がすべて出力される
- 行数固定の定型帳票を作る場合に使われる
- どちらのテーブルをマスタにするか
left
、right
で決める
- 片方のテーブルの情報がすべて出力される
SELECTTS.tenpo_id,TS.tenpo_mei,S.shohin_id,S.shohin_mei,S.hanbai_tankaFROMTenpoShohinTSRIGHTOUTERJOINShohinSONTS.shohin_id=S.shohin_idORDERBYtenpo_id;
corss join
- 実務ではまず使われない
inner join
とouter join
のベースとなる
第8章 SQLで高度な処理を行なう
ウィンドウ関数
OLAP関数とも呼ばれます。例えばrank
関数の場合だと、partition by
がテーブルを横方向にカットします。この区切られた部分がウィンドウという範囲です。それをorder by
が縦方向に順序づけします。
またウィンドウ関数は引数をとらないため()
内は常に空っぽです。
rank
- ランキングを算出する
- 同順位なら後続の順位が飛ぶ
- 1位、2位、2位、4位……
- 同順位なら後続の順位が飛ぶ
- ランキングを算出する
dense_rank
- 後続順位が飛ばない
- 1位、2位、2位、3位……
- 後続順位が飛ばない
row_number
- 一意な連番づけをする
--Oracle、DB2、SQL Server、PostgreSQLSELECTshohin_mei,shohin_bunrui,hanbai_tanka,RANK()OVER(PARTITIONBYshohin_bunruiORDERBYhanbai_tanka)ASrankingFROMShohin;
sum
をウィンドウ関数として使って累計を出す
--Oracle、DB2、SQL Server、PostgreSQLSELECTshohin_id,shohin_mei,hanbai_tanka,SUM(hanbai_tanka)OVER(ORDERBYshohin_id)AScurrent_sumFROMShohin;
avg
を使って移動平均を出す
--Oracle、DB2、SQL Server、PostgreSQLSELECTshohin_id,shohin_mei,hanbai_tanka,AVG(hanbai_tanka)OVER(ORDERBYshohin_idROWSBETWEEN1PRECEDINGAND1FOLLOWING)ASmoving_avgFROMShohin;
- レコードをきちんとした順序に並べるには最後に
order by
を入れるover
内のorder by
は計算順序を決める役割しかない
--Oracle、DB2、SQL Server、PostgreSQLSELECTshohin_mei,shohin_bunrui,hanbai_tanka,RANK()OVER(ORDERBYhanbai_tanka)ASrankingFROMShohinORDERBYranking;
GROUPING
演算子
rollup
- 合計・小計値も
group by
と一緒に出したい時に使う group by ()
とgroup by (shohin_bunrui)
を同時に計算している
- 合計・小計値も
--Oracle、DB2、SQL Server、PostgreSQLSELECTshohin_bunrui,SUM(hanbai_tanka)ASsum_tankaFROMShohinGROUPBYROLLUP(shohin_bunrui);
grouping
- 合計部分に文字列を埋め込める
cube
group by
句のキーのすべての組み合わせを表示する
grouping sets
- 条件を個別指定して抜き出す