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句

参考文献