目次
- 目次
- 概要
- メモ
- 参考文献
概要
DBスペシャリストに向けた学習メモ。
メモ
用語
- 選択:selectで行を絞り込む事。
- 射影:selectで列を絞り込む事。
- 「列」=「項目」=「カラム」=「属性」=「フィールド」
- 「行」=「レコード」=「タプル」
- 3層データモデル
- データモデルを3層に分けるのは、
データ独立
を実現し、変更に強いシステムにする為。- 概念データモデル
- データの内容・概念を纏めた抽象的なモデル。
- システム化対象に対する
概念設計
によって出来上がる。 - 概念設計の方法には、
トップダウンアプローチ
とボトムアプアプローチ
の2種類が有る。
- 論理データモデル
- DBで実際に実装可能なモデル。
- 概念データモデルに対する
論理設計
によって出来上がる。 - DBと、ユーザやAPとを結び付ける為のモノ。
- 概念データモデルを元に論理データモデルを作成する事で、
論理データ独立
が成し遂げられる。- APを改修した際、論理データモデルを改修するたけで良いので、概念データモデルには影響を及ぼさない。
- 逆に、DB構造等を改修した際、概念データモデルを改修するだけで良いので、論理データモデルには影響を及ぼさない。
- 物理データモデル
- 概念データモデル
- データモデルを3層に分けるのは、
- 3層スキーマアーキテクチャ
- 基幹システム
- 業務上必須なシステム。在庫管理・物流管理・販売管理システム等。
- データレイク
- 収集した加工前のデータを保管しておく場所。
- データクレンジング
- データレイクに貯めたデータに対し、データ重複・誤記・表記揺れなどを探し出し、削除・修正・正規化する事。
- データウェアハウス
- データクレンジング後のデータを保管しておく場所。
- データマート
- データウェアハウスから特定の利用者・用途向けに加工して取り出したデータ。
- 更新時異常
- 正規化していないテーブルを更新(Insert・update・delete)した際に起こる、下記3種類の異常。
- タプル挿入時異常
- あるデータ(カラム)を新規作成しようとした際、他のデータ(カラム)も決まらないと挿入できない等。
- タプル更新(修正)時異常
- あるデータ(カラム)を更新しようとした際、そのデータが複数箇所に存在し、一部レコードのみしか更新されない事で、整合性が破綻してしまう等。
- タプル削除時異常
- あるデータ(カラム)を削除しようとした際、他のデータ(カラム)の存在も一緒に消えて失くなってしまう等。
- タプル挿入時異常
- 正規化していないテーブルを更新(Insert・update・delete)した際に起こる、下記3種類の異常。
- 関数従属性
- カラムXの値が決まればカラムYの値が一意に定まる場合、「YはXに関数従属している」と言い、「X→Y」と表現する。
- Xを
決定項
、Yを従属項
と言う。
- 導出属性
- 単価と数量が分かれば、乗算する事で金額が分かるように、他のカラムから演算する事で導出可能な事。
- 情報無損失分解
- 正規化によって分解した表どうしを自然結合したら元の状態に戻せるように分解する事。正規化によって分解した際に元の一部の情報が欠損してしまわない事。
- 外部キー制約
- 「参照制約」とも言う。
- テーブルBの主キーが、テーブルAの外部キーの時、下記2つの制約が発生する。
- テーブルAの外部キーには、テーブルBに存在する値しか入れられない。(テーブルBの主キーに存在しない新たな値をテーブルAの外部キーには入れられない)
- テーブルAの外部キーに存在する値は、テーブルBからは削除できない。
select
distinct(ディスティンクト)
- 重複レコードの排除。
select distinct x from TableName ~
で、select結果に重複が存在する場合は重複排除して結果表示される。(表示行数が減る)select distinct x, y from TableName~
の場合、xとyを組み合わせた表示結果が完全重複している場合に重複排除される。つまり、xとyの片方だけ重複している行同士は排除されない。
coalesce(コアレス)
- 任意のカラムがnullのレコードに対して、代わりの値を表示する。
select coalesce(x, y) from TableName ~
で、カラムxの値がnullの行は、nullの代わりにyを表示する。- 例:
select coalesce(型番, '無し') from 商品;
の場合、型番が存在するレコードはそのまま表示、型番がnullのレコードは「無し」が表示される。
case when then else end
- 任意のカラムに対して、任意の条件の場合に任意の値を表示する。
- 例:
select case when 単価 <= 300 then '割引対象' else '通常価格' end from 商品;
で、単価が300円以下の商品のレコードは「割引対象」を、301円以上の商品のレコードには「通常価格」を、表示する。 - 例:
select case when 型番 is null then '無し' else 型番 end from 商品;
は、select coalesce(型番, '無し') from 商品;
と同義。
where
null
- 比較演算子に利用できない。
- 該当カラムがnullか評価する場合は「x = null」ではなく「x is null」を使う。
in
where x IN (a, b, c)
で、where x=a or x=b or x=c
の意味。
between
where x BETWEEN y and z
で、where x>=y and x<=z
の意味。
all
where x > ALL (2, 3, 10)
で、where x > 10
の意味。
some・any
where x > SOME (2, 3, 10)
・where x > ANY (2, 3, 10)
で、where x > 2
の意味。
exists
- select結果が存在しているかどうかのみを判定する。
- 例:
select 商品名 from 商品 where EXISTS (select * from 売上明細);
- 「存在するかどうか?」しか判定しないため、副問合せの射影部分は何でも良いため、
*
になっている事が多い。
- 「存在するかどうか?」しか判定しないため、副問合せの射影部分は何でも良いため、
- 判定を逆転させたい場合は、
NOT EXISTS
とすれば良い。
order by
- 並べ替え。
order by ○○ ASC
で昇順、order by ○○ DESC
で降順。(デフォルトはASC
。)order by ○○ ASC, △△ DESC
のように、複数カラム指定することも可能。(より左に書いたカラムを優先で並び替えが実施される。)
group by
- 表示レコードを任意のカラムの値でグルーピングする。
- 例:
select 曜日 from 予定表 group by 曜日;
で、「月」「火」・・・「日」という7レコードだけが表示される。 group by
で指定したカラムしか、select表示できない。つまり、上記例でselect 曜日, 予定名 from 〜
とはできない。group by
でグルーピングすると、各グループ内の個別データにはアクセスできないため。- 冷静に考えると、そもそも、曜日が「月」で予定名がバラバラのレコードが複数存在する状況で、「月」1レコードに「予定名」にどのレコードの値を表示すべきか選べない。
集約関数
group by
句でデータをグループ化した後、または、データ全体に対して処理を実行する関数。
count()
- レコード数をカウントする。
select 商品種別コード, count(*) from 商品 group by 商品種別コード;
の場合、商品種別コード毎にグルーピングした後、各グループ内のレコード数をカウントする。- 一方で、
count()
関数の引数に任意のカラム名を指定すると、そのカラムがnullではないレコードの件数をカウントする。- 例えば、
select 商品種別コード, count(型番) from 商品 group by 商品種別コード;
の場合、商品種別コード毎にグルーピングした後、各グループ内の型番
カラムがnullではないレコード数をカウントする。
- 例えば、
- また、
count()
関数の引数の任意カラム名の前にdistinct
を指定すると、そのカラムがnullではない、かつ、重複排除したレコードの件数をカウントする。- 例えば、
select 商品種別コード, count(distinct 最終入荷日) from 商品 group by 商品種別コード;
の場合、商品種別コード毎にグルーピングした後、各グループ内の商品種別コード
カラムがnullではない、かつ、重複排除したレコード数をカウントする。
- 例えば、
having
group by
句でデータをグループ化した後に条件を指定して絞り込む。- 例:
select 商品コード, sum(数量) from 売上明細 group by 商品コード having 商品コード <= 10;
で、group by
で商品コードをグループ化した後に、10以下の商品コードのみに絞り込んでいる。
関係代数
- 複数のテーブルを使った演算を行う。直積・和・差・積・商。
和(UNION)
union
句を使用する。- ベン図で言う
or
の事で、union
句前のselect結果のレコードにプラスで、union
句後のselect結果のレコードも表示する。- そのため、
union
句前後のselect文で指定するカラム数やデータ型が一致している必要が有る。(この特性を和両立
と言う。)
- そのため、
- 重複は排除される。(表示する全てのカラムが同一の場合に「重複」と判断されるため、1カラムでも非同一の場合は排除されない。)
- 重複を排除したくない場合は、
union all
。
- 重複を排除したくない場合は、
- 例:
select 最終入荷日 from 商品 where 商品種別コード = 1 UNION select 最終入荷日 from 商品 where 商品種別コード = 2;
差(EXCEPT)
except
句を使用する。except
句前のselect結果から、except
句後のselect結果を差し引く。(and部分は非表示)- そのため、
except
句前後のselect文で指定するカラム数やデータ型が一致している必要が有る。(この特性を和両立
と言う。)
- そのため、
- 重複は排除される。(表示する全てのカラムが同一の場合に「重複」と判断されるため、1カラムでも非同一の場合は排除されない。)
- 重複を排除したくない場合は、
except all
。
- 重複を排除したくない場合は、
- 例:
select 商品コード from 商品 EXCEPT select 商品コード from 商品 where 商品種別コード = 2;
積(共通集合)(INTERSECT)
intersect
句を使用する。- ベン図で言う
and
の事で、intersect
句前後のselect結果の重複部分を表示する。- そのため、
intersect
句前後のselect文で指定するカラム数やデータ型が一致している必要が有る。(この特性を和両立
と言う。)
- そのため、
- 例:
select 商品コード from 商品 INTERSECT select 商品コード from 商品 where 商品種別コード = 2;
直積(CROSS JOIN)
- 和・差・積が、2テーブルのレコードを連結していた(テーブルの縦幅だけが伸びる)のに対し、直積は、2テーブルのカラムを連結する(テーブルの縦幅に加えて横幅も長くなる)。
- そのため、2テーブルは
和両立
な関係でなくて良い。
- そのため、2テーブルは
- 例:カラムが「商品コード」「商品名」「単価」の「商品」テーブル(3レコード)と、カラムが「店舗コード」「店舗名」「店長コード」の「店舗」テーブル(2レコード)の直積を実行すると、カラム数が6、レコード数が6(3*2)のテーブルが出来上がる。
- SQLの記載方法は下記2種類。
select * from 商品, 店舗;
のように、select対象テーブルを,
区切りで記載する方法。select * from 商品 CROSS JOIN 店舗;
のように、CROSS JOIN
句で記載する方法。
商
- 直積の状態から、直積されてない状態に戻す事。
- 商を行うSQLは存在しない。
- 例:カラム数が6(「商品コード」「商品名」「単価」「店舗コード」「店舗名」「店長コード」)、レコード数が6(3*2)のテーブルの商を実行すると、カラムが「商品コード」「商品名」「単価」の「商品」テーブル(3レコード)と、カラムが「店舗コード」「店舗名」「店長コード」の「店舗」テーブル(2レコード)が出来上がる。
R / S = X
という関係の際、試験問題ではR
とS
が与えられX
(問題の選択肢)を求めると言う形が多い。この際は、「R * X
のレコードが全てR
のレコードに含まれるか?」という観点で見るのが良い。含まれていないレコードが存在する場合は、その選択肢は即刻省く。
結合
内部結合(INNER JOIN)
直積
と同じく、2テーブルのカラムを連結する(テーブルの縦幅に加えて横幅も長くなる)。- 例:
select * from 商品 INNER JOIN 売上明細 ON <条件>;
のように、INNER JOIN
句・ON
句で記載する。 - 実は、下記SQLのような
where
句を用いた直積
でも同じselect結果を得られるが、直積
では2テーブルの全レコードの組み合わせが生成された後にwhere
句で表示結果を絞り込むため、中間データセットが大きくなってしまい処理効率が悪い。一方で、INNER JOIN
句・ON
句を用いた内部結合では、ON
句によって先に絞り込みが行われた後に対象レコードの組み合わせが生成されるため、中間データセットも小さくなり処理効率が非常に良い。そのため、INNER JOIN
句・ON
句を用いた内部結合を使用する事が推奨される。select * from 商品, 売上明細 where 〜;
。
USING
句を使うと、ON
句で記載していた絞り込み条件を簡略化できる。- before:
select 商品名, 数量 from 商品 INNER JOIN 売上明細 ON 商品.商品コード = 売上明細.商品コード;
- after:
select 商品名, 数量 from 商品 INNER JOIN 売上明細 USING (商品コード);
- before:
NATURAL JOIN
句を使うと、絞り込み条件の記載を更に簡略化できる。- before:
select 商品名, 数量 from 商品 INNER JOIN 売上明細 USING (商品コード);
- after:
select 商品名, 数量 from 商品 NATURAL JOIN 売上明細;
- 2テーブルで同名のカラムを自動的に結合条件として使用してくれる。(同名カラムが複数有る場合は、全て用いられるので要注意。)
- before:
左外部結合(LEFT OUTER JOIN)
- 左側テーブルの全レコード(条件一致しないレコードも含め)と、右側テーブルで条件に一致した行を、列結合して表示する。
- 左側テーブルには存在するが、条件的に右側テーブルには存在しないレコードは、右側テーブル側のカラムを
NULL
で表示する。 - 例:
select 商品名, 売上数 from 商品 LEFT OUTER JOIN 売上明細 ON 商品.商品コード = 売上明細.商品コード;
右外部結合(RIGHT OUTER JOIN)
左外部結合
の、左右逆パターン。
全外部結合
- 両テーブルの全レコードを表示し、条件一致しないレコードのカラムには
NULL
を表示する。 左外部結合
と右外部結合
を同時にやるイメージ。- 例:
select 商品名, 数量 from 商品 FULL OUTER JOIN 売上明細 ON 商品.商品コード = 売上明細.商品コード;
副問合せ
- SQLの実行結果を用いてSQLを実行する為に、SQL文の中に入れ子でSQLを記載する事。
- 例:
select 商品名 from 商品 where 商品コード = (select 商品コード from 売上明細 where 売上番号 = 1);
- 内側(副問合せ)のSQLが先に実行され、その結果を受けて外側のSQLが実行される。
相関副問合せ
- 内側(副問合せ)SQL文の中で、外側SQLで登場するテーブルを用いた、副問合せの事。
- 例:
select 商品名 from 商品 where exists (select * from 売上明細 where 商品コード = 商品.商品コード);
- 外側SQLで登場する商品テーブルを、副問合せにて使用している。
- 普通の
副問合せ
とは違い、外側SQLのfrom
が走ってレコードを取得する度に1レコードずつ副問合せが実行されるため、普通の副問合せ
よりも処理速度は落ちる。
CREATE
- テーブル作成するSQL。
- 基本は、下記のように、カラム名とデータ型を指定するだけ。
CREATE TABLE テーブル名 (カラム名 データ型, ・・・);
CREATE TABLE 返品 (返品番号 INTEGER, 売上番号 INTEGER, 返品日付 DATE, 理由 VARCHAR(100));
- 各カラムに特定の条件を付与する場合は、下記のように指定する。
CREATE TABLE テーブル名 (カラム名 データ型 制約, ・・・);
CREATE TABLE 返品 (返品番号 INTEGER PRIMARY KEY, 売上番号 INTEGER UNIQUE NOT NULL, 返品日付 DATE NOT NULL, 理由 VARCHAR(100) DEFAULT NULL);
- 「返品番号」カラム:主キー制約。(主キー制約を付与すると、同時に非NULL制約も付与される。)
- 「売上番号」カラム:ユニーク(一意)制約・非NULL制約。(制約の記載順序はどっちでも良い。)
- 「返品日付」カラム:非NULL制約。
- 「理由」カラム:デフォルト値をNULLに指定。
制約の種類
- 主キー(PRIMARY KEY)制約
<カラム名> PRIMARY KEY
句を使用する事で、そのカラムを主キーに設定する。PRIMARY KEY (<カラム名>)
でも可能。
- 主キー制約を付与すると、同時に、一意(UNIQUE)制約・非NULL制約も付与される。
- 一意(UNIQUE)制約
<カラム名> UNIQUE
句を使用する事で、そのカラムに重複した値の挿入を禁止する。UNIQUE (<カラム名>)
でも可能。
- 重複禁止なだけなので、主キー(PRIMARY KEY)制約とは異なり、NULL値の入力が可能。
- 非NULL(NOT NULL)制約
<カラム名> NOT NULL
句を使用する事で、そのカラムにNULL値の挿入を禁止する。
- DEFAULT制約
<カラム名> DEFAULT <任意の値>
句を使用する事で、そのカラムのデフォルト値を設定する。- カラムへのデータ入力を省略した場合、デフォルト値がカラムに自動格納される。
- 外部キー(参照・参照整合性・FOREIGN KEY)制約
DROP
- テーブルを削除するSQL。
DROP TABLE テーブル名;
VIEW(ビュー)
- 実在しない仮装テーブル(導出テーブル)を作成するSQL。もっと言うと、実テーブルに対する決まった形のSQL文を定型化したモノ。
CREATE VIEW <ビュー名> (<カラム名, ・・・>) AS SQL文;
- セキュリティと利便性の向上が目的。
- 下記条件を満たす場合は、VIEWに対して追加・更新・削除が可能。
- 複数の行を1行に纏めていない事。
- VIEWに含まれていないカラムに非null制約が設定されていない事。
- VIEWに追加・更新した際、VIEWに含まれていないカラムにはnullが設定されるため。
- 結合している場合には、対象のテーブルが特定できる事。
GRANT(権限付与)
- テーブル・VIEW毎に、誰に何の操作を許可するか設定する。
GRANT <権限>, ・・・ ON <テーブル名> TO <ユーザ名>;
- <ユーザ名>部分を
PUBLIC
にすると、全員という意味。
- <ユーザ名>部分を
GRANT SELECT ON 会員 TO daisuke;
で、daisukeユーザに、会員テーブルのselect権限を付与できる。REVOKE SELECT ON 会員 FROM daisuke
で、daisukeユーザから、会員テーブルのselect権限を剥奪できる。
スーパータイプ・サブタイプ
- 「AはBとCに分けられる」場合、Aをスーパータイプ、B・Cをサブタイプと呼ぶ。
排他的サブタイプ
と共存的サブタイプ
:- 排他的サブタイプ:
- あるデータがBとCの両方に属することは無く、どちらか一方にのみ属する事。
- リレーション表記は、スーパータイプから1本線が伸び、△部分で2本に分岐する形になる。
- 共存的サブタイプ:
排他的サブタイプ
と逆で、あるデータがBとCの両方に属する事が有り得る事。- リレーション表記は、スーパータイプから2本線に分かれた形で線が伸び、それぞれの線に△が記載された形になる(△部分で分岐する形ではない)。
排他的サブタイプ
の場合は「〜区分」、共存的サブタイプ
の場合は「〜フラグ」、と呼ばれることが多い。
- 排他的サブタイプ:
- サブタイプ間の共通項目は、サブタイプではなくスーパータイプに持たせる。一方で、特定のサブタイプしか持たない項目はサブタイプに持たせる。
- サブタイプには、スーパータイプの主キーを持たせる。一方で、スーパータイプには、どのサブタイプかを判断するための項目を持たせる。
-
-
-
-
-
-
-
SELECT文の実行順序
select文の各句の実行順序は下記の順番。
- from
- join
- where
- group by
- 集約関数
- having
- select
- order by
- limit
上記の通り、limit句は1番最後に実行されるため、limitで表示行数を絞ったとしても、DBサーバへの処理負荷や処理時間は全件処理とほぼ変わらない(らしい)。
また、sum()
やcount()
等の集約関数
は、グルーピングされたデータに対して処理する関数のため、group by
より前のwhere
句等では実行不可。
正規化
正規化とは、更新時異常
を起こさないように、1箇所1事実
を実現する為に、テーブルを分解する事。
第1正規系
- 全てのカラムが単一の値をとる状態の事。
- 1つのカラムに複数の値が入っていたり、碁盤のような綺麗なマス目状態になっていない場合、
非正規系
。
第2正規系
- 全ての非キー属性(候補キーではないカラム)が、各候補キーに完全関数従属している状態の事。言い換えると、「候補キーの一部のカラムによって一意に定まる非キー属性が有るか?」。無ければ既に第2正規系、有れば
部分関数従属性
を排除できていないため、第2正規化が必要。 - コツは、先に、候補キーの組み合わせを全て洗い出す。候補キーにならなかった残りのカラムを全て非キー属性として、「候補キーの一部のカラムによって一意に定まる非キー属性が有るか?」を検討する。
- 第2正規化する際は、部分関数従属性における候補キーを分解先のテーブルの主キーとし、非キー属性はそのまま分解先のテーブルに移動させる。
第3正規系
- 「主キー以外のカラムが決まれば一意に定まるカラムが有るか?」。無ければ既に第3正規系、有れば
推移的関数従属性
を排除できていないため、第3正規化が必要。 - 第3正規化する際は、推移的関数従属性における推移元カラムを分解先のテーブルの主キーとし、非キー属性はそのまま分解先のテーブルに移動させる。