第 3 章 「SELECT ステートメント(1)」 ~ 初めて学ぶ Transact-SQL ~
NEC
Eラーニング事業部
鈴木 智行
2003 年 2 月 17 日
目次
0. 販売データベース
1. ワイルドカード文字
2. NULL 値の比較
3. 既定の列名の変更
4. 重複行の除去
5. データの並び替え
6. データのグループ化
7. 復習問題
0. 販売データベース
0.販売データベース
今回使用している販売データベースは今回のコラム用に作成したものであり、図 0-1 に示すとおり、5 つのテーブルから構成されています。
図 0-1 販売データベースを構成する 5 つのテーブル
列名の下部の記述はデータ型と呼ばれるもので、情報の種類を指定することで列に格納できる値を制限します。このデータ型はテーブル作成するときに必要な指定であり、たくさんの種類が存在しますが、今回のコラムではその一部を表 0-2 に紹介します。
データ型 |
説明 |
---|---|
char(n) |
固定長文字型、n は格納できる最大文字数を指定する |
varchar(n) |
可変長文字型、n は格納できる最大文字数を指定する |
nchar(n) |
Unicode 固定長文字型、n は格納できる最大文字数を指定する |
nvarchar(n) |
Unicode 可変長文字型、n は格納できる最大文字数を指定する |
int |
数値型で 4 バイトの格納領域をもつ |
smalldatetime |
分精度の日付時刻型 |
表 0-2 SQL Server で利用できるデータ型 ( 抜粋 )
1. ワイルドカード文字
ワイルドカード文字は LIKE 演算子と共に利用して文字型の列に対するパターン検索に使用します。文字や日付時刻の指定は’(シングルコーテーション)を使用し、Unicode 文字の指定にはそれに加え N を先頭につけるので注意してください。
ワイルドカードには表 1-1 で示される種類があります。
ワイルドカード文字 |
説明 |
---|---|
% |
0 個以上の文字を示す |
_ |
任意の 1 文字を示す |
[] |
指定した範囲またはセットに含まれる任意の 1 文字を示す |
[^] |
指定した範囲またはセットに含まれない任意の 1 文字を示す |
表 1-1 SQL Server で使用できるワイルドカード
(例1) 商品テーブルから商品名が 「~あんぱん」 である商品コードと商品名を取得する(画面 1-2)。
画面 1-2 商品名が「~あんぱん」である商品コードと商品名を取得(後方一致)
(例 2) 顧客テーブルから顧客コードが「P~」 もしくは 「S~」 である顧客コードと顧客名を取得する (画面 1-3)。
画面 1-3 顧客コードが P か S で始まる顧客コードと顧客名を取得 (前方一致)
ワイルドカードを使用する際の注意点は、ワイルドカード自身を含む文字列を検索したいケースの場合です。例えば商品テーブルから 「胚芽 50 % 入り~」 という % が含まれている商品を検索したい場合はどうすればいいでしょうか。この場合はワイルドカード文字を通常の文字として使用するための特殊な文字 (エスケープ文字) を宣言して検索を行ないます(画面 1-4)。
画面 1-4 商品名が「胚芽 50 % 入り~」である商品名を取得
画面 1-4 では ESCAPE 句で文字’#’をエスケープ文字と宣言し、文字’%’の直前に定義して’%’を通常の文字として扱うように指示しています。
2. NULL 値の比較
入力されていない、まだ決まっていない値を NULL といいます。SQL Server 以外の DBMS の中には長さ 0 の文字列とみなすものもありますが、SQL Server では NULL 値は長さ 0 の文字列でもありませんし、数値 0 でもなく、厳密に区別されます。また NULL 値を許可するかどうかは列の属性によって決まるので、NULL 値が格納されない列もあります。
NULL 値と比較するような条件を指定した場合は注意が必要です。= (等号比較演算子) や<> (不等号比較演算子) を使用した場合は ANSI_NULLS の設定によって動作が変わります。ANSI_NULLS は SET ステートメントで ON/OFF の切り替えを行ないます。
・SET ANSI_NULLS ON (OFF)
1) SET ANSI_NULLS ON の場合
ANSI_NULLS を ON にすると SQL-92 の動作に準拠します。SQL-92 では NULL との比較はできません。結果はどのような場合でも FALSE になります(画面 2-1)。
画面 2-1 結果は全て FALSE となり、結果は返ってこない
2) SET ANSI_NULLS OFF の場合
ANSI_NULLS を OFF にすると SQL-92 の動作に従いません。すなわち = (等号比較演算子) を使用したときは、NULL 値が存在すれは TRUE、NULL 値が存在しなければ FALSE、<> (不等号比較演算子) を使用したときは、NULL 値が存在すれば FALSE、NULL 値が存在しなければ TRUE となります(画面 2-2)。
画面 2-2 NULL 値の存在によって、異なる結果が返ってくる
しかし ANSI_NULLS の設定はサーバーレベルやデータベースレベルおよび ANSI_DEFAULT などの設定やプロバイダの種類によって大きく変わります。したがって Transact-SQL ステートメントが意図どおり動作するようにするためには、ANSI_NULLS の設定とは無関係に動作するように指定することが重要でしょう。そのためには = (等号比較演算子) や<> (不等号比較演算子) のかわりに IS NULL、IS NOT NULL を使用します。IS NULL、IS NOT NULL は ANSI_NULLS の設定の影響をうけません。すなわち IS NULL を使用したときは、NULL 値が存在すれは TRUE、NULL 値が存在しなければ FALSE、IS NOT NULL を使用したときは、NULL 値が存在すれば FALSE、NULL 値が存在しなければ TRUE となります(画面2-3)。
画面 2-3 IS NULL 、 IS NOT NULL を使用すれば ANSI_NULLS の影響をうけない
以前のバージョンで作成された Transact-SQL では IS NULL、IS NOT NULL を使用していない場合が多く見受けられます。NULL と比較するような Transact-SQL を新規に作成する場合には IS NULL および、IS NOT NULL を使用するように心がけてください。
3. 既定の列名の変更
SELECT ステートメントを実行した結果はリレーショナル形式で返され、その結果セットを表す列名にはデータを取得した元のテーブルの列名 (既定の列名) が使用されます。結果データの列名を変更したい場合は選択リストに AS キーワードを使用して列名を作成し(これを別名と呼ぶ場合もある)、既定列名を置き換えます。第 1 章で紹介した式のように、元のデータを加工して結果を返している場合などには列名がつきません。列名がつかないとビューを作成するケースでは不都合が生じる場合があるので、なるべく列名を指定する習慣をつけましょう (画面 3-1)。
画面 3-1 AS キーワードを指定して列名を作成する
4. 重複行の除去
DISTINCT キーワードを使用すると結果セットに重複行がある場合にはそれを除去してくれます。冗長性が必要ない場合に指定してください (画面 4-1)。
画面 4-1DISTINCT キーワードを使用して冗長性を排除する
5. データの並び替え
SQL Server 2000 では結果データがどの順序で返されるか保証されていません。思い通りの順序で結果を返したい場合は ORDER BY 句を使用します。ORDER BY 句で指定する基準には列名 (選択リストに含まれていなくても可能)、別名、式などが使用でき、複数指定することも可能です。
並び替えには 2 つの方法があり降順 (大きいもの順) には DESC キーワードを (画面 5-1)、昇順 (小さいもの順) には ASC キーワードを使用します。ASC キーワードは ORDER BY 句の既定値なので特に指定する必要はありません。
画面 5-1 ORDER BY 句を利用してデータを降順に並び替える
ORDER BY 句によって並び替えられた結果セットは TOP キーワードを使用して返す行を制限し、例えば 「営業成績の良い上位 5 名の営業マン一覧」 や 「1 月の売上が悪い下位 10 パーセントの商品一覧」 などを検索することができます。
Top n では行数を、Top n PERCENT ではパーセンテージを指定します (画面 5-2)
画面 5-2 Top キーワードで結果セットを制限する
しかし、もし最後の行と同じ値をもつ行があったとしても Top n や、Top n PERCENT では結果セットから除外されます。そういったデータを表示したい場合には WITH TIES 句と併用してください。
画面 5-3 Top キーワードと WITH TIES 句を併用して結果セットを制限する
6. データのグループ化
結果セットはあるデータをキーとしてグループ化ができます。GROUP BY 句でグルーピングする列を指定します。グループ化するときによく一緒に使用されるのが第 1 章でご紹介した集計関数であり、例えば注文テーブルにおいて顧客コード毎に注文数量の合計を表示したい場合は 画面 6-1 のようになります。
画面 6-1 GROUP BY 句でグループ化を行う
GROUP BY 句で指定されるすべての列 (集計式は除く) が、選択リストに含まれていないとエラーが発生するので注意してください。
WHERE 句を指定すると SQL Server は WHERE 句の条件に合う行だけをグループ化します。すなわち WHERE 句は GROUP BY 句の前に評価されます。グループ化をする必要がないデータは WHERE 句でフィルタリングしてください(画面 6-2)。
画面 6-2 WHERE 句でフィルタリングを行ってグループ化する
それに対し、HAVING 句を使用すると結果セットに含めるべきグループに対して条件を設定することができます。すなわち WHERE 句は GROUP BY 句の後に評価されます。通常は HAVING 句では集計関数を条件指定に使用します(画面 6-3)。
画面 6-3 グループ化した後に HAVING 句でフィルタリングを行う
また WHERE 句を満たさないグループをNULLとして表示したい場合には GROUP BY 句に ALL キーワードを使用します (画面 6-4)。
画面 6-4 ALL キーワードを使用して WHERE 句を満たさないグループを表示
ただし HAVING 句はALLキーワードを無視するので、指定しても意味はありません。
7. 復習問題
では、今までの復習をしてみましょう。復習問題を実際に試してみたい方はこちら (createlabemv.sql) から演習データベースと社員テーブルを作成するスクリプトファイルをダウンロードして、クエリアナライザ等で実行してください。
社員テーブル
社員番号 |
社員名 |
性別 |
所属部署 |
所在地 |
※ただし以下の条件があるものとする
同じ所属部署は同じ所在地である
所属部署には総務部第一課、総務部第二課、営業部第一課、営業部第二課しかない
新入社員は配属先が未定 (所属部署と所在地が NULL) である
問題 1
女性社員全員の社員番号と社員名を表示するための Transact-SQL 文を記述しなさい
画面 7-1 問題 1 の結果
問題 2
新入社員全員の社員名を表示するためのTransact-SQL文を記述しなさい
画面 7-2 問題 2 の結果
問題 3
社員番号が 3 番から 5 番までの社員番号と社員名を表示するための Transact-SQL 文を記述しなさい
画面 7-3 問題 3 の結果
問題 4
所属部署が総務部第一課、総務部第二課である社員名を表示するための Transact-SQL 文を記述しなさい
画面 7-4 問題 4 の結果
問題 5
所属部署と各所属部署に在籍する社員の人数を表示するための Transact-SQL 文を記述しなさい、ただし結果セットでの社員の人数にあたる列名は 「在籍人数」 という名前にし、新入社員は NULL の部署の在籍人数に数えること
画面 7-5 問題 5 の結果
問題 6
3 人以上在籍する所属部署と所在地を表示するための Transact-SQL 文を記述しなさい、ただし新入社員は数にいれないこと
画面 7-6 問題 6 の結果
問題 7
在籍人数が多い順に所属部署を並び替え、第 2 位までの所属部署と在籍する社員の人数を表示するための Transact-SQL 文を記述しなさい、ただし結果セットでの社員の人数にあたる列名は 「在籍人数」 という名前にし、同点 2 位も含み、新入社員は数にいれないこと
画面 7-7 問題 7 の結果
次回も引き続き SELECT ステートメントについてご紹介します。
鈴木 智行 : NEC Eラーニング事業部に所属。入社以来、インストラクタとして教育業務に従事。汎用機、UNIX を経て、1994 年より マイクロソフト認定トレーナー (MCT) として、管理者向け教育を担当。SQL Server は 4.21a から携わっており、現在は主に SQL Server 2000 に関わるデータベース教育を中心に担当。 Windows 2000 および SQL Server 2000 での MCSE,MCDBA を取得しており、情報処理技術者試験のテクニカルエンジニア(データベース)も取得済。 SQL Server の優位性をアピールできるように Oracle Gold も取得した。今後 Oracle Plutinum を取得予定し、日々データベースを極めることに努力している。