LoginSignup
2
0

More than 3 years have passed since last update.

日本語並び順の考察

Last updated at Posted at 2019-09-17

【序文】

日本語の並び順の問題に関する考察。

【環境】

SQLServer SQLCMD
2017 14.0.1000.169

設定はデフォルト。
但しコマンドプロンプトのコードページは 65001。

【よくある問題】

以下のような部署名が格納されたテーブルがあったとする。

部署名
第一営業部
第二営業部
第三営業部

部署名でソートした結果が以下。

1> SELECT [Value] FROM STRING_SPLIT(N'第一営業部,第二営業部,第三営業部', N',') ORDER BY [Value];
2> GO
Value
-----------------
第一営業部
第三営業部
第二営業部

(3 行処理されました)

これは期待した結果ではない。というかこれは文字コードの問題であり SQLServer、DB の問題ではない。
しかし、DB での実装でしばしば問題になるテーマなので取り上げてみた。

【解決策】

単純に表示順を持たせる方法が一般的だろう。

表示順 部署名
1 第一営業部
2 第二営業部
3 第三営業部

クエリでは、表示順列でソートすると。
もしクエリ側だけで無理やり何とかするなら以下。

1> SELECT [Value] [部署名] FROM STRING_SPLIT(N'第一営業部,第二営業部,第三営業部', N',')
2> ORDER BY REPLACE(REPLACE(REPLACE([Value], N'一', N'1'), N'二', N'2'), N'三', N'3')
3> ;
4> GO
部署名
-----------------
第一営業部
第二営業部
第三営業部

(3 行処理されました)

酷い方法である。しかし開発の現場では、こんな付け焼刃的なコードがゴロゴロしているという……。

【余談】

そもそも漢数字の並び順ってどうなっているんだろう? というのが最初のきっかけだった。

1> SELECT [Value] FROM STRING_SPLIT(N'〇,一,二,三,四,五,六,七,八,九,十', N',') ORDER BY [Value];
2> GO
Value
---------------------












(11 行処理されました)

滅茶苦茶。大字は?

1> SELECT [Value] FROM STRING_SPLIT(N'零,壱,弐,参,肆,伍,陸,漆,捌,玖,拾', N',') ORDER BY [Value];
2> GO
Value
---------------------












(11 行処理されました)

そもそも漢字って読み仮名順が基本だっけ? 簡単に言えば、あいうえお順。慣用的な並び順になる訳ない。
しかし、英語圏でも使われるであろうローマ数字や丸数字だとまともなんだよな。そういえばローマ数字ってゼロがないんだね。

1> SELECT [Value] FROM STRING_SPLIT(N'Ⅰ,Ⅱ,Ⅲ,Ⅳ,Ⅴ,Ⅵ,Ⅶ,Ⅷ,Ⅸ,Ⅹ', N',') ORDER BY [Value];
2> GO
Value
-------------------











(10 行処理されました)
1> SELECT [Value] FROM STRING_SPLIT(N'⓪,①,②,③,④,⑤,⑥,⑦,⑧,⑨,⑩,⑪,⑫,⑬,⑭,⑮,⑯,⑰,⑱,⑲,⑳', N',') ORDER BY [Value];
2> GO
Value
-----------------------------------------






















(21 行処理されました)

同様の流れで。

1> SELECT [Value] FROM STRING_SPLIT(N'❶,❷,❸,❹,❺,❻,❼,❽,❾,❿', N',') ORDER BY [Value];
2> SELECT [Value] FROM STRING_SPLIT(N'Ⓐ,Ⓑ,Ⓒ,Ⓓ,Ⓔ,Ⓕ,Ⓖ,Ⓗ,Ⓘ,Ⓙ,Ⓚ,Ⓛ,Ⓜ,Ⓝ,Ⓞ,Ⓟ,Ⓠ,Ⓡ,Ⓢ,Ⓣ,Ⓤ,Ⓥ,Ⓦ,Ⓧ,Ⓨ,Ⓩ', N',') ORDER BY [Value];
3> SELECT [Value] FROM STRING_SPLIT(N'ⓐ,ⓑ,ⓒ,ⓓ,ⓔ,ⓕ,ⓖ,ⓗ,ⓘ,ⓙ,ⓚ,ⓛ,ⓜ,ⓝ,ⓞ,ⓟ,ⓠ,ⓡ,ⓢ,ⓣ,ⓤ,ⓥ,ⓦ,ⓧ,ⓨ,ⓩ', N',') ORDER BY [Value];
4> SELECT [Value] FROM STRING_SPLIT(N'⑴,⑵,⑶,⑷,⑸,⑹,⑺,⑻,⑼,⑽,⑾,⑿,⒀,⒁,⒂,⒃,⒄,⒅,⒆,⒇', N',') ORDER BY [Value];
5> SELECT [Value] FROM STRING_SPLIT(N'⒜,⒝,⒞,⒟,⒠,⒡,⒢,⒣,⒤,⒥,⒦,⒧,⒨,⒩,⒪,⒫,⒬,⒭,⒮,⒯,⒰,⒱,⒲,⒳,⒴,⒵', N',') ORDER BY [Value];
6> SELECT [Value] FROM STRING_SPLIT(N'⒈,⒉,⒊,⒋,⒌,⒍,⒎,⒏,⒐,⒑,⒒,⒓,⒔,⒕,⒖,⒗,⒘,⒙,⒚,⒛', N',') ORDER BY [Value];
7> GO
Value
-------------------











(10 行処理されました)
Value
---------------------------------------------------



























(26 行処理されました)
Value
---------------------------------------------------



























(26 行処理されました)
Value
---------------------------------------





















(20 行処理されました)
Value
---------------------------------------------------



























(26 行処理されました)
Value
---------------------------------------





















(20 行処理されました)

これらの文字は以下を使わせていただいた。多謝。
入力しづらい丸英数字のメモ

再び漢字に戻る。
手当たり次第確認してみる。

1> SELECT [Value] FROM STRING_SPLIT(N'一,万,億,兆,京,垓,?穣,溝,澗,正,載,極', N',') ORDER BY [Value];
2> GO
Value
-------------------------














(13 行処理されました)

因みに本来入力したクエリは以下。
𥝱 はサロゲートペア文字みたいでコマンドプロンプト上では扱えない。うーむ。サロゲートペア入門:CodeZine(コードジン) によれば U+25771 らしい。だから何だって話だけど。

SELECT [Value] FROM STRING_SPLIT(N'一,万,億,兆,京,垓,𥝱,穣,溝,澗,正,載,極', N',') ORDER BY [Value];
GO

引き続き思いつくままに。

1> SELECT [Value] FROM STRING_SPLIT(N'小,中,高,大', N',') ORDER BY [Value];
2> SELECT [Value] FROM STRING_SPLIT(N'起,承,転,結', N',') ORDER BY [Value];
3> GO
Value
-------





(4 行処理されました)
Value
-------





(4 行処理されました)
1> SELECT [Value] FROM STRING_SPLIT(N'春,夏,秋,冬', N',') ORDER BY [Value];
2> SELECT [Value] FROM STRING_SPLIT(N'都,道,府,県', N',') ORDER BY [Value];
3> GO
Value
-------





(4 行処理されました)
Value
-------





(4 行処理されました)

惜しい。> 加減乗除

1> SELECT [Value] FROM STRING_SPLIT(N'市,区,町,村', N',') ORDER BY [Value];
2> SELECT [Value] FROM STRING_SPLIT(N'加,減,乗,除', N',') ORDER BY [Value];
3> GO
Value
-------





(4 行処理されました)
Value
-------





(4 行処理されました)
1> SELECT [Value] FROM STRING_SPLIT(N'甲,乙,丙,丁', N',') ORDER BY [Value];
2> SELECT [Value] FROM STRING_SPLIT(N'士,農,工,商', N',') ORDER BY [Value];
3> GO
Value
-------





(4 行処理されました)
Value
-------





(4 行処理されました)
1> SELECT [Value] FROM STRING_SPLIT(N'子,丑,寅,卯,辰,巳,午,未,申,酉,戌,亥', N',') ORDER BY [Value];
2> GO
Value
-----------------------













(12 行処理されました)

左右も逆なら前後も逆。

1> SELECT [Value] FROM STRING_SPLIT(N'前,後,左,右', N',') ORDER BY [Value];
2> SELECT [Value] FROM STRING_SPLIT(N'古,今,東,西', N',') ORDER BY [Value];
3> GO
Value
-------





(4 行処理されました)
Value
-------


西


(4 行処理されました)

レディファーストでさえない。冠婚葬祭は惜しい。

1> SELECT [Value] FROM STRING_SPLIT(N'老,若,男,女', N',') ORDER BY [Value];
2> SELECT [Value] FROM STRING_SPLIT(N'冠,婚,葬,祭', N',') ORDER BY [Value];
3> GO
Value
-------





(4 行処理されました)
Value
-------





(4 行処理されました)
1> SELECT [Value] FROM STRING_SPLIT(N'喜,怒,哀,楽', N',') ORDER BY [Value];
2> SELECT [Value] FROM STRING_SPLIT(N'風,林,火,山', N',') ORDER BY [Value];
3> GO
Value
-------





(4 行処理されました)
Value
-------





(4 行処理されました)

大喜利と化してきたのでこの辺で。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0