SQL Server

SELECT文

SELECT文は指定したデータを取得・出力するクエリです。出力する対象にはテーブルのカラムを指定することが多いですが、任意の出力したい数値や文字を指定することもできます。

SELECT文は6つの句から成ります。記述順に、SELECT句・FROM句・WHERE句・GROUP BY句・HAVING句・ORDER BY句です。SELECT句以外は省略することができますが省略した場合でも記述順は守らなければなりません。

SELECT句

SELECT句では出力対象となるデータを指定します。また、関数を使ってデータを加工することもできます。SELECT文を構成する6つの句のうち、SELECT句だけは省略不可となっています。基本的な文法は次の通りです。

SELECT ALL/DISTINCTオプション TOPオプション出力対象1 AS ヘッダー名,出力対象2 AS ヘッダー名,出力対象n AS ヘッダー名;

ALL/DISTINCTオプション

重複したレコードの出力の是非を決めるオプションです。ALLを指定すると重複が許可されます。DISTINCTを指定すると重複したレコードは1レコードにまとめられて出力されます。どちらも指定しなかったときはALLで指定されます。

-- 重複レコードをまとめないSELECT ALL*;-- 重複レコードをまとめるSELECT DISTINCT*;-- 省略した場合はALL指定として処理されるSELECT*;

TOPオプション

TOPオプションはTOPオプションを指定しなかったときに出力される結果のうち、上位何件を表示するかを指定するオプションです。件数の指定には具体的な件数を指定する方法と、本来の出力件数に対する割合を指定する方法の2通りがあります。

-- 値指定(以下例では上位5件まで表示する)SELECT TOP(5)*;-- 割合指定(以下例では上位30%を出力する)SELECT TOP(30) PERCIENT*;

なお、TOPオプション直後の小括弧は省略することができますが推奨されません。

SELECT TOP 5*;SELECT TOP 30 PERCIENT*;

出力対象の指定方法

出力対象の指定には3つ方法があります。

1つ目は直接値を指定する方法です。

-- 3と出力SELECT1 + 2;-- 12と出力SELECT'1' + '2';

2つ目はFROM句で指定したテーブルに含まれるカラムを指定する方法です。

SELECTname,priceFROMtable_1;

3つ目はCASE式を使う方法です。CASE式は同じレコードに属する別カラムの値に応じて出力する値を変化させることができます。

SELECTname,price,CASEWHEN price => 10000 WHEN 'High-end'WHEN price < 1000 WHEN 'Low-end'ELSE 'Middle-range'FROMtable_1;

ヘッダー名変更

SELECT文によって出力された結果のヘッダー名は変更することができます。ASキーワードの後ろに別名を記述します。

SELECTname AS '商品名',price AS '売価'FROMtable_1;

ASは省略することもできます。

SELECTname '商品名',price '売価'FROMtable_1;

FROM句

FROM句ではSELECT文で取得するデータを指定します。対象にはテーブルの他、テーブル変数などもFROM句で指定することができます。

-- 文法SELECT*FROM取得するデータ対象1 WITHオプション AS テーブル別名,取得するデータ対象2 WITHオプション AS テーブル別名,取得するデータ対象3 WITHオプション AS テーブル別名;

複数のテーブルを指定したとき、SELECT句で指定するカラム名はテーブル名.カラム名で指定します。ASキーワードを使ってテーブルの別名を指定したときは本来のテーブル名と別名、どちらを使っても問題ありません。

SELECTtable_1.name,t1.price,table_2.name,t2.priceFROMtable_1 AS t1,table_2 AS t2;

WITHオプション

WITHオプションを付与すると、WITHオプションを指定しなかったときよりも弱いロックでクエリを実行することができます。何らかの処理が行われているテーブルからデータを取得したとき、あるいはSELECT文を実行したことで他のクエリの処理の邪魔をしたくないときに便利です。

注意すべき点としてはWITHオプションを含めて、SQL Serverでは全くロックを掛けないクエリというのは実行できません。そのため一部のクエリと並行して実行すると問題が起きることがあります。

SELECT*FROMtable_1 WITH(NOLOCK);

JOIN演算子

JOIN演算子は2つのテーブルを結合して、初めから1つのテーブルであったかのような振る舞いを実現する演算子です。JOIN演算子はさらにCROSS JOIN演算子INNER JOIN演算子LEFT OUTER JOIN演算子RIGHT OUTER JOIN演算子FULL OUTER JOIN演算子の5つに分けられます。

CROSS JOIN演算子は2つのテーブル同士を掛け合わせた全ての組み合わせを出力します。つまり、3レコードのテーブルと3レコードのテーブルをCROSS JOIN演算子で結合すると、3 * 3 で9レコードのテーブルとして扱われるわけです。正直使い道はあまりありません。

SELECT*FROMtable_1 CROSS JOIN table_2;-- 実は以下クエリでも同じ結果が得られますSELECT*FROMtable_1,table_2;

INNER JOIN演算子は結合条件で指定した条件を満たすレコードのみ結合・出力します。処理の流れとしては、1.演算子左辺のテーブルの1行目を確認2.結合条件を満たした演算子右辺のレコードと結合3.結合されていたら出力し、そうでないなら出力しない4.演算子左辺のレコードの次行を参照するという流れになります。

SELECT*FROMtable_1 INNER JOIN table_2 ON table_1.id = table_2.id;

LEFT OUTER JOIN演算子はINNER JOIN演算子と似ていますが、演算子左辺のレコードに限っては結合していなくても出力します。反対に、RIGHT OUTER JOIN演算子は演算子右辺のレコードに限っては結合していなくても出力します。そして、FULL OUTER JOIN演算子は演算子両辺のテーブルに格納されたレコードを少なくとも1回は出力します。ちなみにOUTERキーワードは省略してもかまいません。

-- LEFT OUTER JOIN演算子例文SELECT*FROMtable_1 LEFT OUTER JOIN table_2 ON table_1.id = table_2.id;-- RIGHT OUTER JOIN演算子例文SELECT*FROMtable_1 RIGHT OUTER JOIN table_2 ON table_1.id = table_2.id;-- FULL OUTER JOIN演算子例文SELECT*FROMtable_1 FULL OUTER JOIN table_2 ON table_1.id = table_2.id;-- OUTERキーワードを省略しても問題無いSELECT*FROMtable_1 LEFT JOIN table_2 ON table_1.id = table_2.id;SELECT*FROMtable_1 RIGHT JOIN table_2 ON table_1.id = table_2.id;-- RIGHT OUTER JOIN演算子例文SELECT*FROMtable_1 FULL JOIN table_2 ON table_1.id = table_2.id;

WHERE句

WHERE句は出力するレコードを条件式を使って指定することができます。SELECT句ではカラムを、WHERE句ではレコードを指定することで欲しいデータを得ることができます。

-- 条件を1つ指定SELECT*FROMtable_1WHEREname = 'ABC';-- 条件を複数指定SELECT*FROMtable_1WHEREname > 100 ANDname < 500;

GROUP BY句

GROUP BY句ではSELECT句で指定したデータ対象を同じ値でまとめることができます。まとめると何が良いかというと、1つには指定したデータ対象の重複が無くなりますので、データの種類がよく分かります。

SELECTcategoryFROMtable_1GROUP BYcategory;--実は以下クエリでも同じ結果が得られますSELECT DISTINCTcategoryFROMtable_1;

ただ、重複したレコードをまとめることがGROUP BY句の目的ではありません(何せDISTINCTオプションで代用できるのですから)。GROUP BY句は関数のカテゴリの1つ――集計関数と併用することで各データごとの平均や合計を知るために用いられます。以下のクエリは各カテゴリごとのポイントの平均を求めるクエリです。

SELECTcategory,AVG(point)FROMtable_1GROUP BYcategory;

HAVING句

HAVING句では集計関数によって、まとめられた値を対象に出力するレコードを絞ることができます。やっていること自体はWHERE句と同じですが、こちらは集計関数でまとめられたデータのみに対して使えます。まとめられていないデータに対してHAVING句は使えません。

SELECTcategory,AVG(point)FROMtable_1GROUP BYcategoryHAVINGAVG(point) = 5;

ORDER BY句

ORDER BY句では出力した結果の並びを整えることができます。並び変える基準となる対象を指定し、その後ろにASC(昇順)DESC(逆順)を指定します。ASC・DESCを指定しなかった場合、ASCが自動的に適用されます。

SELECTrecode_id,update_date,product_priceFROMtable_1ORDER BYupdate_date