SQLの勉強1
Abstract
SQLのSELECTについて勉強したのでメモ.
Introduction
SQLのSELECTの難しさとして,次のようなものが挙げられる: (1) SELECTはDBに格納されている値をフィルタリングしたり変換したりと,複数の手順から構成される処理であるにもかかわらず,手続き型プログラミング言語とは異なり,一文のSQLとして記述する点(注: サブクエリを使うと分割できる); (2) 記述順序と評価順序が異なる点; (3) それぞれの句に使える位置の制約がある点.
この難しさを解決するために,次の三点を理解したい: (1) SELECT句を含むSQL文がどのような構造で記述されるか; (2) このSQL文がどのような順序で評価されるか; (3) それぞれの句が何を受け取り,何を返し,どの位置で使えるか.
SELECTの構造
基本構文は次のようなもの:
SELECT FROM WHERE GROUP BY HAVING ;
ここでの基本構文とは,その位置でしか使えず,1つのSELECTステートメントに1度しか使用できない句を並べたもの. ちなみに
- ORDER BY句はウィンドウ関数内でも使えるので除外.記述順序はHAVINGの後
- LIMIT句は標準SQLではない.記述順序はORDER BYの後
各句の評価順序,入力ドメイン,記法と引数,出力は以下の通り:
- FROM(): FROM < TABLE > -> [W x H]
- WHERE(PRE=[W x H1]): WHERE < BOOL > -> [W x H]
- < BOOL >には,PREの各行に対して真偽を与えるような論理式を記述する.オペランドとしてカラムとスカラが使える.
- それぞれの句は,評価時点で処理済みのテーブル(PRE)を暗黙に受け取っている
- 判定用のカラムを作成してJOINすることで相関サブクエリを書き換えられる場合がある
- GROUP BY(PRE=[W x H]): GROUP BY < PRE.cols > -> [(W + G) x H]
- 指定したカラム群< PRE.cols > (集約キー)において重複する行に同じグループインデックスを割り当てるイメージ.この段階ではまだ行数は減っていない(集約キー以外の情報も保存されている)
- Gはグループインデックスのバリエーション(つまりグループ数)とする.次元としての[(W + G) x H]の記法は,各行にグループインデックス上のone-hotベクトルを付与するイメージ
- 以降,集約関数が使用可能になる
- HAVING(PRE=[(W + G1) x H1]): HAVING < BOOL > -> [(W + G) x H]
- 各グループに対する真偽値を返す論理式しか< BOOL >に使えないので,オペランドとして使えるカラムにはSELECTと同じ制約がある
- SELECT(PRE=[(W1 + G) x H]): SELECT < PRE.cols > -> [W x G]
- SELECTは1グループ1行で出力するので,GROUP BYで指定したカラム群か,集約関数でグループ毎に集約した結果しかSELECTのカラムに指定できない
- GROUP BYを指定しない場合は1レコード1行で出力.ただし,集約関数は全レコードを1グループと考えた挙動になる
Future Work
- サブクエリ・スカラサブクエリ
- 相関サブクエリ
- ビュー
- WITH句