データベース千夜一夜第3回

レコードの選択と整列
~SELECT命令をしっかり理解する
長谷川裕行
有限会社 手國堂

レコードの並べ替え(整列)~ORDER BY句

単にレコードを抽出するだけでは、実際の処理に役立ちません。抽出したレコード群をユーザーに提示する場合、最低限、レコードはユーザーから見て意味のある順序に並んでいる必要があります。


- レコードの並び順は正しいか? -

テーブル内のレコードは、通常、基本表(マスターテーブル)ならIDフィールド(「商品ID」など、レコードを識別するための値を持つフィールド)の値順に並んで表示されます。これは、テーブルの内容を表示するプログラム(クエリアナライザやEnterprise Managerなど)のインターフェイスが、主キーやインデックスに指定したフィールドの値を基準に、レコードを並べ替えて表示するよう設計されているためです。

基本表以外のテーブルでは、日付や伝票番号などやはり主キーかインデックスに指定したフィールド、あるいはたまたま一番先頭(左端)に配置されたフィールドの値の順に並んでいるはずです。

但し、これはあくまでレコードを表示するプログラムの仕様によるもので、どのようなRDBMSでも、またどのようなツールでも同じ結果になる訳ではありません。


- 元データの並び順は不定 -

テーブルに記録されているレコードは、実際には主キーフィールドやインデックス・フィールドの値の順でもなければ、時系列的にレコードが記録された順に並んでいるのでもありません。

多くのRDBMSは、データベース生成時に基本的なディスク領域を確保しておき、最初はその中に記録された順にレコードを書き込んでいきますが、何度も削除や書き込みを繰り返していくうちに、ハードディスクのフラグメンテーションと同じ理屈で記録領域の「虫食い」が生じます。

それでもまだ未使用領域があればそこに追記していきますが、未使用領域がなくなってしまえば、過去に削除されて虫食い状態となっている領域に、新たなレコードを記録していくことになります。こうして時が経つにつれ、レコードの物理的な順序はバラバラになっていくのです。

こうなると、実際にディスクに書き込まれている順には、ほとんど意味がなくなってしまいます。そのため、プログラムの側が「それなりに意味のある順序」に並べ替えて表示しているのです。

多くの場合、RDBMSに付属のツールでテーブルを最適化できますが、ユーザーが必ずそれを行っているとは限りません※2

※2 本来は、データベースの管理責任者が定期的に最適化を行うべきです。また、受注などで開発する業務システムには、管理用の機能としてテーブルの最適化処理を設けておくべきです。しかし現実には、特に小さなシステムだと、こういった機能を設けていないものもたくさんあります


- ORDER BY句で明確に並べ替える -

このように、レコードの並び順が不定であるのですから、データベースを扱う処理の中でSELECT文を使ってレコードを取り出した場合、その結果を直接ユーザーに提示するのであれば、明確な意図を持ってレコードを並べ替えておかなければなりません。

レコードを並べ替えるにはORDER BY句を用います。構文は以下のような書式になります。

  SELECT <フィールド名>(, <フィールド名>, <フィールド名>...)
  FROM <テーブル名> ORDER BY <キーフィールド名> [ASC | DESC]

ORDER BY句はFROM句の後に添え、続けて並べ替えの基準とするフィールド(キーフィールド)を指定します。

単にORDER BY <キーフィールド名>とだけ指定すると、キーフィールドの値でレコードを昇順に並べます。後にASCを付けた場合も同じです。降順に並べるにはDESCを指定します。


- 昇順指定と降順指定 -

テーブル「商品_mr」を、在庫数の少ない順(昇順)に並べ替えて取り出すには、以下のようなSQLを記述します。

  SELECT 商品ID, 品名, 販売単価, 仕入単価, 在庫
  FROM 商品_mr ORDER BY 在庫 ASC

「ASC」は省略できるので、以下のようなSQLでも同じ結果となります。

  SELECT 商品ID, 品名, 販売単価, 仕入単価, 在庫
  FROM 商品_mr ORDER BY 在庫

在庫数の多い順(降順)に並べるなら、以下のようなSQLになります。

  SELECT 商品ID, 品名, 販売単価, 仕入単価, 在庫
  FROM 商品_mr ORDER BY 在庫 DESC

「在庫数」などデータ型が数値となっているフィールドの場合は、単純に値の代償に基づいて並べられます。char、varcharのように文字や文字列をキーフィールドとした場合は、文字コードの大小によって並べ替えられます。





- 簡単だが重要な機能 -

SQLを解説した書籍などでは、ORDER BY句によるレコードの並べ替えは、案外あっさりと簡単に説明されているようです。実際、非常に単純な機能なので、あまりくどくどと解説する必要はないと思います。しかし、SQL文に明確な並べ替えの指定が記述されていない場合、先述したようにRDBMSの仕様によって異なる基準が適用されることになります。これは、あまりよいことではありません。

特に、SELECT文によって抽出された結果(レコードセット)を対象に、プログラムで特定のレコードを検索するような処理を作る場合、レコードの並び順によって検索効率が大きく変わる場合があります※3

特に、リレーションを設定した複雑なSQLでは、ORDER BY句によるレコードの並べ替え指定をつい忘れがちです。また、初期の状態ではレコードは自然な状態に並んでいるため、動作テストの段階ではこの問題に気が付かないこともよくあります。システムが実稼働を始めて数箇月経ってから、表示されるレコードの順序が何かおかしい……と、問題が露呈することになります。要注意です。

※3 もちろん、レコードの検索はSQLを発行するか別に作ったクエリファイルで処理すべきであり、プログラムのコードで対応すること自体が非効率的なのですが、場合によってはそうせざるを得ないこともあります


トップページ
レコードの抽出(選択)~SELECT命令
レコードの並べ替え(整列)~ORDER BY句
レコードの並び順は正しいか?
元データの並び順は不定
ORDER BY句で明確に並べ替える
昇順指定と降順指定
簡単だが重要な機能
SELECT命令の処理結果とレコードセット
あとがき
Copyright © MESCIUS inc. All rights reserved.