MS Access を使った人ならだれしも, ソートされたデータを見て 「なんでこんな順序に並ぶの? 本当に並んでるの?」 と首をひねりたくなった経験があるでしょう。 しかし, 実際にどういう順序で並ぶかをきちんと記述したものは存在しないようです。 この文章が MS ACCESS のソート順の謎の解明に少しでも役立てば幸いです。
目次:
あらかじめ注意しておかなければならないのは, ACCESS のソート順では, 互いに異なる文字列について, 必ずしも大小の差がないということです。 ひらがなとカタカナ, 半角と全角, 大文字と小文字などは区別しません。 したがって, ひらがなとカタカナの混じったデータは, ソートするたびに順序が変わって, まるでソート順が存在しないかのように見えることがあります。
この現象自体はそれほど奇怪ではありません。 ACCESS 以外でも, 「大文字と小文字を区別しないインデックス」 をサポートしているデータベース管理ソフトウェアは数多くあります。
しかし, MS ACCESS の場合は等しくなる場合が非常に多いこと, どうして等しくなるのか明らかでない場合が多いこと, 「大文字と小文字を区別する」というオプションが存在しない (バイナリで比較する場合は除いて) ことなど, 扱いにくさが群を抜いています。
この現象は, ソート順の解明のしにくさに直接つながります。 適当にデータを作成して, ソートしてみたからといって, その結果が大小の違いであるかどうかがわからないのです。 もう一度ソートすると違う順序で並ぶかもしれません。
ソートしただけでソート順がわからないのなら, どうやって調べればいいでしょうか。 Access Basic を使って, 大小比較演算子で調べる, という方法を試してみましょう。 まずすべての 1文字データを比較してみます。 Access ではデータの終わりにスペースを入れることができませんから, 比較データの終わりに「!」を付け加えて比較します(こういう場合の常套手段)。 すると, こういう結果になりました。
いきなり推移律が成り立たない! ううーん。 この方法はだめみたいです…というか, これじゃどんな方法でもダメなんじゃないかと目の前がまっくらになりました。
気を取り直して, 上記データをソートしてみました。 すると不思議。 こんどは「−!」よりも「ー!」の方が大きくなります。 大小比較演算子にバグがあるのか, 比較の順序とソートの順序が違うのか…。
とにかく Access Basic は使えないということがわかったので, まずソートしてみた結果に SELECT DISTINCT の QUERY をかけて同値データを取り除く, という手間のかかる方法で調査することにしました。
日本語のソート順で問題になるのは濁点・長音・拗音などの処理ですが, ACCESS はなかなかがんばっています。 大まかに下のようなアルゴリズムを使って並べています。
「濁音仮名」と「清音仮名+濁点」は同じとみなします(例: 「び」=「ひ」+「゛」)。 ここでおもしろいのは, 「濁点・半濁点はかな以外にもつけられる」ということです。 さらに濁点を複数つけることもできます。 半濁点 1個は(なぜだか知りませんが)濁点 2個ぶんと同じとみなします (例: 山あ < 山゛あ < 山゛゛あ = 山゜あ < 山゛゜あ < 山い)。
もっとすごい話。 「℃」は C に半濁点のついたものとみなします。 ウソだと思ったら「℃」をデータに入れて, 「C゜」で検索してご覧なさい。
濁点については他にもいろいろおもしろい話がありますが後回しにします。
先に述べた「無視される違い」ですが, 次のようなものがあります。
以上のうち, 全角と半角の違いについては, JIS X 0201 と JIS X 0208 の記号について, どれとどれが対応しているのかが自明ではないので, とくに注意すべき対応関係を以下に書いておきます。
| 半角 | 全角 | 備考 |
|---|---|---|
| 20 | 8140 | SPACE, JIS規格では全角と半角の差とはしていない |
| 22 | FA57 | QUOTATION MARK, FA57 は IBM拡張文字 |
| 27 | FA56 | APOSTROPHE, FA56 は IBM拡張文字 |
| 2D | 817C | HYPHEN-MINUS, JIS規格では全角と半角の差とはしていない |
| 5C | 818F | YEN SIGN |
| 60 | 814D | GRAVE ACCENT |
| 7E | 8160 | TILDE, JIS規格では全角と半角の差とはしていない |
以上のほかに, 「いくつあっても無視される文字」というのがあります。 典型的には JIS X 0208 の未定義領域にある字がそうです (F040-F9FC のユーザー定義文字は無視しません) が, それ以外に以下の文字があります(もちろん対応する半角の濁点も同様)。
| 文字 | SJIS | 説明 |
|---|---|---|
| ゛ | 814A | 濁点(前に文字がない場合) |
| ゜ | 814B | 半濁点(前に文字がない場合) |
| 〇 | 815A | 漢数字のゼロ |
| ◯ | 81FC | 合成用丸 |
ACCESS では「一」も「一〇〇〇〇」も同じになってしまうのです!!
合成用丸を無視するのはいいとして, 漢数字のゼロを無視するのは (いくら形が似ているからといって) 合点が行きません。
なお, 「無視する」といいましたが, 空文字列よりは大きいことになっています。 これだけ例外です。
以下の 4 文字(全角と半角を別に数えれば 6文字) を本文章では「ハイフン文字」と呼ぶことにします。
| 文字 | SJIS | 説明 |
|---|---|---|
| 80 | 80H | |
| ' | 27, FA56 | APOSTROPHE |
| - | 2D, 817C | HYPHEN-MINUS, MINUS SIGN |
| ‐ | 815D | HYPHEN |
ハイフン文字は上記の「◯」などと同様たいてい無視されるのですが, ハイフン以外の部分が同値の場合, 以下のようなきわめて複雑な方法で比較します。
これを効率よく実装するのはけっこう頭の体操になりますよ。
なんだかよくわからないタイトルですが, 記号の並び順についてです。
記号は(上記の無視される文字を除いて)英数字や仮名・漢字などより小さいものとみなします。 問題は記号どうしをどういう順序で並べるかですが, これがなかなか一筋縄では行きません。 本文章では便宜上, 記号を 「記述記号1・記述記号2・数学記号・幾何学図形・矢印・罫線記号・一般記号・飾り文字」 の 8類(この順に並ぶ)に分けて説明します。
53文字あります。下のようにおおむね Unicode 順に並びます。 コードをカッコでくくってあるのは例外です。
| Unicode | 0020 | 0021 | 0022 | 0023 | 0024 | 0025 | 0026 | 0028 | 0029 | 002a |
|---|---|---|---|---|---|---|---|---|---|---|
| 文字 | ' ' | ! | " | # | $ | % | & | ( | ) | * |
| Unicode | 002c | (3001) | 002e | (3002) | 002f | 003a | 003b | 003f | 0040 | 005b |
| 文字 | , | 、 | . | 。 | / | : | ; | ? | @ | [ |
| Unicode | 005c | 005d | 005e | 005f | 0060 | 007b | 007c | 007d | 007e | 00a6 |
| 文字 | \ | ] | ^ | _ | ` | { | | | } | ~ | U |
| Unicode | 00a8 | 00af | 00b4 | 2018 | 2019 | 201c | 201d | 2032 | 2033 | 3008 |
| 文字 | ¨ |  ̄ | ´ | ‘ | ’ | “ | ” | ′ | ″ | 〈 |
| Unicode | 3009 | 300a | 300b | 300c | 300d | 300e | 300f | 3010 | 3011 | 3014 |
| 文字 | 〉 | 《 | 》 | 「 | 」 | 『 | 』 | 【 | 】 | 〔 |
| Unicode | 3015 | 301d | 301f | |||||||
| 文字 | 〕 |
区点(。)がピリオド(.)の次に並ぶこと, 読点(、)がコンマ(,)の次に並ぶこと, 005c が円記号でなくて「\」であることに注意。
以下の 2記号がこの順に並びます。
| 文字 | SJIS | Unicode | 説明 |
|---|---|---|---|
| 〃 | 8156 | 3003 | 同じく記号 |
| 〆 | 8159 | 3006 | しめ |
43文字。やはり「おおむね」 Unicode の順に並ぶのですが, 00B1 と 00AB の順序だけ逆になっています。
| Unicode | 002b | 003c | 003d | 003e | 00b1 | (00ab) | 00bb | 00d7 | 00f7 | 2200 |
|---|---|---|---|---|---|---|---|---|---|---|
| 文字 | + | < | = | > | ± | ≪ | ≫ | × | ÷ | ∀ |
| Unicode | 2202 | 2203 | 2207 | 2208 | 220b | 2211 | 221a | 221d | 221f | 2220 |
| 文字 | ∂ | ∃ | ∇ | ∈ | ∋ | √ | ∝ | ∠ | ||
| Unicode | 2225 | 2227 | 2228 | 2229 | 222a | 222b | 222c | 222e | 2234 | 2235 |
| 文字 | ‖ | ∧ | ∨ | ∩ | ∪ | ∫ | ∬ | ∴ | ∵ | |
| Unicode | 223d | 2252 | 2260 | 2261 | 2266 | 2267 | 2282 | 2283 | 2286 | 2287 |
| 文字 | ∽ | ≒ | ≠ | ≡ | ≦ | ≧ | ⊂ | ⊃ | ⊆ | ⊇ |
| Unicode | 22a5 | 22bf | 2312 | |||||||
| 文字 | ⊥ | ⌒ |
11文字あります。 やはり Unicode 順に並ぶのですが, 同じ形の図形(四角・三角・逆三角・ひし形・丸) のバリアントどうしは, Unicode の値の差だけ濁点をつけたものとみなします。 (例: ■゛=□, ◎゛=●, ○゛゛゛ =◎) なんでだー!!
| Unicode | 25a0 | 25a1 | 25b2 | 25b3 | 25bc | 25bd | 25c6 | 25c7 | 25cb | 25ce | 25cf |
| 文字 | ■ | □ | ▲ | △ | ▼ | ▽ | ◆ | ◇ | ○ | ◎ | ● |
6文字あります。 Unicode 順でなく, 時計まわり(?)に並ぶようです。 ただし,右二重矢印(⇒)は右矢印(→)より濁点14個ぶん!! 大きいものに等しいとみなします。 (⇒ = →゛゛゛゛゛゛゛゛゛゛゛゛゛゛)
なんでか知りません。 もちろん濁点14個のかわりに半濁点7個でもかまいません。
| Unicode | 2191 | 2192 | 21d2 | 2193 | 2190 | 21d4 |
|---|---|---|---|---|---|---|
| 文字 | ↑ | → | ⇒ | ↓ | ← | ⇔ |
32文字あります。 Unicode 順に並びますが, 例によって罫線の太さの差は,濁音と同じように処理します。 すなわち,細い罫線に対して太い罫線は Unicode の値の差のぶんだけ濁点がついたものとみなします。 (例: ─ < ─゛= ━ < ─#; ┌ < ┌ ゛< ┌゛゛< ┌゛゛゛= ┏ < ┌#)
| Unicode | 2500 | 2501 | 2502 | 2503 | 250c | 250f | 2510 | 2513 | 2514 | 2517 |
|---|---|---|---|---|---|---|---|---|---|---|
| 文字 | ─ | ━ | │ | ┃ | ┌ | ┏ | ┐ | ┓ | └ | ┗ |
| Unicode | 2518 | 251b | 251c | 251d | 2520 | 2523 | 2524 | 2525 | 2528 | 252b |
| 文字 | ┘ | ┛ | ├ | ┝ | ┠ | ┣ | ┤ | ┥ | ┨ | ┫ |
| Unicode | 252c | 252f | 2530 | 2533 | 2534 | 2537 | 2538 | 253b | 253c | 253f |
| 文字 | ┬ | ┯ | ┰ | ┳ | ┴ | ┷ | ┸ | ┻ | ┼ | ┿ |
| Unicode | 2542 | 254b | ||||||||
| 文字 | ╂ | ╋ |
16文字あります。 以下の 3点の解釈をほどこすによって, Unicode 順にならんでいるものとみなすことが可能です。
| Unicode | 00a2 | 00a3 | 00a5 | 00a7 | 00ac | 00b0 | 00b6 | 00b7 | 2020 | 2021 |
|---|---|---|---|---|---|---|---|---|---|---|
| 文字 | ¢ | £ | ¥ | § | ¬ | ° | ¶ | ・ | † | ‡ |
| Unicode | 2025 | 2026 | 2030 | 203b | 3012 | 3013 | ||||
| 文字 | ‥ | … | ‰ | ※ | 〒 | 〓 |
7文字あります。 おおむね Unicode 順に並んでいますが, なぜか★と☆の順だけひっくり返っています。
| Unicode | 2606 | 2605 | 2640 | 2642 | 266a | 266d | 266f |
|---|---|---|---|---|---|---|---|
| 文字 | ☆ | ★ | ♀ | ♂ | ♪ | ♭ | ♯ |
なんでこう細かい違いがあるんでしょうね。
41字あります。 数字は値の順に並びます。 同じ値を持つ数字は,算用数字 < 丸付き数字 < ローマ数字の順にならびます。 算用数字の全角と半角, ローマ数字の大文字と小文字は区別しません。 丸付き数字は算用数字にアクセント記号をつけたものと考えます。 (例: 1 < 1゜< @ < 1! < T) 一番大きいのは「∞」です(笑)。 なにもここまで凝らなくても…。
注意: 比較はあくまで文字単位で行うので, 文字列をソートしても数値の順にはなりません。
| Unicode | 0030 | 0031 | 2460 | 2160 | 0032 | 2461 | 2161 | 0033 | 2462 | 2162 |
|---|---|---|---|---|---|---|---|---|---|---|
| 文字 | 0 | 1 | @ | T | 2 | A | U | 3 | B | V |
| Unicode | 0034 | 2463 | 2163 | 0035 | 2464 | 2164 | 0036 | 2465 | 2165 | 0037 |
| 文字 | 4 | C | W | 5 | D | X | 6 | E | Y | 7 |
| Unicode | 2466 | 2166 | 0038 | 2467 | 2167 | 0039 | 2468 | 2168 | 2469 | 2169 |
| 文字 | F | Z | 8 | G | [ | 9 | H | \ | I | ] |
| Unicode | 246a | 246b | 246c | 246d | 246e | 246f | 2470 | 2471 | 2472 | 2473 |
| 文字 | J | K | L | M | N | O | P | Q | R | S |
| Unicode | 221e | |||||||||
| 文字 | ∞ |
38字あります。 アルファベット順に並びます。 アクセント記号つきアルファベットや合字もここに入ります。 大文字と小文字, 全角と半角は区別しません。
先に述べたとおり, 「Å」は「A」にアクセントがついた文字, 「℃」は C に半濁点のついた文字とみなします。 (例: AA < ÅA < AB)
それ以外の字については文字単位の比較であって, 文字列が必ずしもアルファベット順に並ぶわけではありません。 (例: c < cz < t {合字} < d)
| Unicode | 0041 | (212b) | 0042 | 0043 | (2103) | (33c4) | (339d) | 0044 | 0045 | 0046 |
|---|---|---|---|---|---|---|---|---|---|---|
| 文字 | A | Å | B | C | ℃ | t | p | D | E | F |
| Unicode | 0047 | 0048 | 0049 | 004a | 004b | (338f) | (33cd) | (339e) | 004c | 004d |
| 文字 | G | H | I | J | K | s | q | L | M | |
| Unicode | (338e) | (339c) | 004e | (2116) | 004f | 0050 | 0051 | 0052 | 0053 | |
| 文字 | u | r | o | n | Y | O | P | Q | R | S |
| Unicode | 0054 | (2121) | 0055 | 0056 | 0057 | 0058 | 0059 | 005a | ||
| 文字 | T | Z | U | V | W | X | Y | Z |
アルファベット順に並びます。 大文字と小文字は区別しません。
原則としてアルファベット順に並びます。 大文字と小文字は区別しません。 ただし, 「е」と「ё」はアクセント記号の有無の違いとみなします。 (例: е < ё < ев)
五十音順に並びます。 字の大小・清音と濁音などについては先に述べたとおりです。 なお, 「小さな字」には「ヵ」「ヶ」を含みます。
シフトJISコード順に並びます。
| SJIS | 875f | 8760 | 8761 | 8762 | 8763 | 8764 | 8765 | 8766 | 8767 | 8768 |
|---|---|---|---|---|---|---|---|---|---|---|
| 文字 | ミリ | キロ | センチ | メートル | グラム | トン | アール | ヘクタール | リットル | フット |
| SJIS | 8769 | 876a | 876b | 876c | 876d | 876e | ||||
| 文字 | カロリー | ドル | セント | パーセント | ミリバール | ページ |
原則として, シフトJISコード順に並びます。 「仝」および漢字の合字もここに含まれます。 拡張漢字は IBM のコード順に並びます。
例外として, 丸付き漢字・括弧付き漢字は丸を取り除いた文字の次に並びます。 (例: 右 < 右大臣 < < 宇; 株 < 株式 < X < 兜)
| ソートしたとき最小の漢字は | 「仝」(SJIS:8157) |
| 拡張漢字を除く最大の漢字は | 「熙」(SJIS:eaa4) |
| 最初の拡張漢字は | 「\」(SJIS:fa5c) |
| 最後の拡張漢字は | 「K」(SJIS:fc4b) |
シフトJISコード順に並びます。
コード a0, fd, fe の文字がこの順に並びます。
長音と踊り字については先に簡単に述べましたが, もうちょっと正確に書きます。 このクラスに属する字には次の7字があります。 (注意: 「〃」は「記述記号2」に属します。また「仝」は漢字です。)
| Unicode | 30fd | 30fe | 309d | 309e | 3005 | 30fc | 2015 |
| 文字 | ヽ | ヾ | ゝ | ゞ | 々 | ー | ― |
単独で出てきた場合, 踊り字・長音符号は他のどの字よりも大きいものとみなされます。 この場合, 7字の間には大小の差はなく, 完全に同値です。
仮名の直後にこのクラスの字が来た場合,下の表のように評価されます。
| 長音符号 | 仮名踊り字 | 漢字踊り字 | ||
|---|---|---|---|---|
| (ー,―) | (ヽゝ) | (ヾゞ) | (々) | |
| 子音 | ゼロ | 前字を継承 | 前字を継承 | 前字を継承 |
| 清濁 | 常に清音 | 常に清音 | 常に濁音 | 半濁音より大 |
| 母音 | 前字を継承 | 前字を継承 | 前字を継承 | 前字を継承 |
| 大きさ | 前字を継承 | 前字を継承 | 前字を継承 | 前字を継承 |
長音符号の直前が「ん」の場合, 長音符号は「ん」として評価されます。
長音・踊り字つきの文字列をそうでない文字列と比較した場合, 清濁・仮名の大小まで考えて,それでも決着がつかない場合,
の順に並びます。 例:
踊り字・長音を複数ならべる事もできます。 (例: いーい < いーー < いーう)
直前の文字が非仮名の場合, 長音符号・踊り字は直前の文字 (ただし, ÅはA, ёはеに直す)を繰り返したものと完全に同値になります。 清濁については仮名の場合と同じです。 (例: Åー = ÅA, 梶R = 括, 山ゞ = 山山゛)
これで私の Access ソート順の巨大な仕様の解析を終わりますが, どなたかエミュレートするプログラムを作ってみませんか?
実はあまりにも煩瑣にわたるので説明を省略した部分があります。 ハイフンの後ろに踊り字がついた場合, ハイフンを繰り返したものとみなすのか, とか。 興味のある人はこのへんを試してみてください。
Windows98 で Unicode を使えば, 丸付きの「株」など, 大量の新たな合字を使用できます。 そのとき ACCESS のソート順はどうなるのでしょうか。 楽しみ, 楽しみ。
参考文献: