2013年4月3日水曜日

◆その他の SQL-92 規格

サブクエリ(副問い合わせ)

SQL では、SELECT ステートメントの中に SELECT ステートメントを記述して、入れ子にして
利用することができます。このようなクエリは、サブクエリ(副問い合わせ)と呼ばれています。

Let's Try
  1. まずは、”給与が最も高い社員” を検索してみましょう。これは、次のようにサブクエリを利
    用して、WHERE 句の条件式へ給与の最大値(MAX(給与))を与えることで、結果を取得す
    ることができます。

    SELECT * FROM 社員
    WHERE 給与 = (SELECT MAX(給与) FROM 社員)


    image
    給与が最も高い社員(松田さん)を取得できたことを確認できます。
    このように SELECT ステートメントをカッコで囲むことで、SELECT ステートメントを入れ
    子にすることができます。
  2. 次に、”平均給与よりも高い給与をもらっている社員” を取得してみましょう。

    SELECT * FROM 社員
    WHERE 給与 > (SELECT AVG(給与) FROM 社員)


    image

    サブクエリとして、給与の平均値(AVG(給与))を WHERE 句の条件式へ与えることで、"平均給与よりも高い給与の社員" を取得することができます。

    Note: サブクエリの SELECT ステートメントの結果が複数件ある場合
    サブクエリでは、カッコ内の SELECT ステートメントの結果が複数件ある場合は、「=」や「>」などの比較演算子を利用するとエラーになります。たとえば、次のように GROUP BY 句を使って、"部門ごとの給与の最大値(MAX)" を取得し、その社員を取得するようにすると、結果はエラーになります。
    image
    このエラーを回避するには、次のように、IN 演算子を利用することができますが、取得した結果は正しくありません(余分なデータが取得されています)。
    image
    “鈴木 太郎” さんの給与は30 万円で部門番号 ”10” の中での最大給与ではありません。部門番号 ”10” の中での最大給与は、“松田 裕太”さんの 70 万円です。一方、“小笠原 翔”さんは、部門番号 ”20“ の社員で、部門番号 “20”の中では最大給与の 30 万円です。このように、正しくない結果が返るのは、カッコ内のステートメントが返す値が「70 万円と 30 万円」で、次のように解釈されてしまっているためです。
    image
    したがって、これを解決するには、次のように SELECT ステートメントの結果を “テーブル” のように扱って、内部結合するようにします。
    image
    部門番号ごとの最大給与の結果に対して、「b」という名前を付けてテーブルのように扱っているところがポイントです。これを図解すると、次のようになります。
    image
    部門番号ごとの最大給与の結果「b」と「社員」テーブルを結合することで、部門ごとの最大給与を取得している社員を抽出できるようになります。このように SELECT ステートメントの結果をテーブルのように利用する方法は、「インライン ビュー」とも呼ばれています。
UNION ALL

SQL では、UNION ALL を利用すると、複数の SELECT ステートメントの検索結果を連結でき
るようになります。構文は、次のとおりです。

image

Let's Try
  1. 社員番号 1~3 の社員を、それぞれ別々の SELECT ステートメントで取得し、結果を
    UNION ALL で連結してみましょう。

    SELECT * FROM 社員 WHERE 社員番号 = 1
     UNION ALL
    SELECT * FROM 社員 WHERE 社員番号 = 2
     UNION ALL
    SELECT * FROM 社員 WHERE 社員番号 = 3


    image
    この結果は、次の SELECT ステートメントを実行した場合と同じになります。
    image
    このように、UNION ALL 句を使用すると、2 つ以上の SELECT ステートメントの結果を連
    結して 1 つの結果にすることができます。

    Note: UNION ALL と UNION
    UNION ALL 句は、単純に SELECT ステートメントの結果を連結するだけなので、結果に重複行があった場合にもそのまま連結します。これに対して、結果に重複があった場合に、重複行を排除して連結することができる「UNION 句」(ALL が付かないもの)があります。
    たとえば、UNION ALL 句を利用した場合の結果は、次のとおりです。
    image
    これに対して、UNION 句を利用した場合の結果は、次のとおりです。
    image
    このように、UNION 句では、重複行を削除した結果を取得することができます(その分、UNION ALL よりも、UNION の方がパフォーマンス上のオーバーヘッドがあります)。

    Note: UNION ALL はデータ型と列数が同じであれば連結可能
    UNION ALL と UNION では、データ型と列数が同じであれば、列名が違っても、全く関係ないテーブル同士でも、結果を連結することが可能です。したがって、次の SQL はエラーにはなりません。
    image

    社員番号と部門場号は、全く関係のないデータですが、UNION ALL や UNION は、単純な結果の ”連結” を行っているだけなので、1 つの結果として取得することができます。

CASE 式

SQL では、CASE 式を利用すると、Visual Basic での「Select Case」や C 言語系と Java の
「Switch」と同じような複数の条件分岐を行えるようになります。構文は、次のとおりです。

image

Let's Try
  1. 次のように入力して、部門番号の値をもとに、部門名を表示するようにしてみましょう。部門
    番号が "10" の場合は "総務部"、部門番号が "20" の場合は "営業部”、これ以外の場合は "その他”と表示してみます。
    image
    このように、CASE 式を使用すると、列の値をもとに、別の値を表示できるようになります。
  2. 次に、入社日の値をもとに、"2000 年以降に入社した社員" と "1990 年以降に入社した社
    員"、"1980年以降に入社した社員"、"それ以外の社員" と表示されるようにしてみましょう。
    image

    Note: CASE 式は選択リスト以外でも利用可能
    CASE 式は、単独では使用することができませんが、ステートメント内であれば、ORDER BY 句や GROUP BY 句、
    WHERE 句、UPDATE の SET 句などで利用することも可能です。

0 件のコメント:

コメントを投稿