Posted at

MySQL - select文でorder by句が正しく効かない場合がある

More than 5 years have passed since last update.

qiitaのアカウントを作成したものの、これまで全く投稿をしていなかったので、

そろそろ何か投稿しなければと思い立ち、初投稿を試みることにしました。

仕事中にうっかりハマってしまった内容を中心に書いていきたいと思います。

今回のテーマは「MySQL - select文でorder by句が正しく効かない場合がある」というものです。


例えば、MySQLに以下のような定義のテーブルを作成します。

-- メンバーテーブル

CREATE TABLE member (
member_id int NOT NULL, -- メンバーID
first_name varchar(45) DEFAULT NULL, -- 名前
birth_date date DEFAULT NULL, -- 生年月日
address varchar(45) DEFAULT NULL, -- 住所
PRIMARY KEY (member_id)
);

このテーブルに以下のようなデータが登録されているとします。

+-----------+------------+------------+----------+

| member_id | first_name | birth_date | address |
+-----------+------------+------------+----------+
| 1 | Eric | 1960-10-10 | New York |
| 2 | Pat | 1959-12-13 | Ohio |
| 3 | Billy | 1953-03-19 | America |
| 4 | Paul | 1966-11-06 | Illinois |
+-----------+------------+------------+----------+

このテーブルから、member_idの降順でデータを取得してみたいと思います。

通常、以下のselect文のように、order by句でmember_idの降順(desc)を指定するかと思います。


select文①

select

member_id,
first_name,
birth_date,
address
from
member
order by
member_id desc
;

実行結果は、以下のようになることが予想できると思います。


実行結果①

+-----------+------------+------------+----------+

| member_id | first_name | birth_date | address |
+-----------+------------+------------+----------+
| 4 | Paul | 1966-11-06 | Illinois |
| 3 | Billy | 1953-03-19 | America |
| 2 | Pat | 1959-12-13 | Ohio |
| 1 | Eric | 1960-10-10 | New York |
+-----------+------------+------------+----------+


ここで、実験をしてみたいと思います。

あえてそれぞれの列に別名を指定してみることにします。


select文②

select 

member_id as "メンバーID",
first_name as "名前",
birth_date as "誕生日",
address as "住所"
from
member
order by
"メンバーID"
desc
;

それぞれの列に日本語で別名を付け、order by句にも別名を指定します。

では、このSQLを実行してみます。すると、以下のような結果となりました。


実行結果②

+------------+-------+------------+----------+

| メンバーID | 名前 | 誕生日 | 住所 |
+------------+-------+------------+----------+
| 1 | Eric | 1960-10-10 | New York |
| 2 | Pat | 1959-12-13 | Ohio |
| 3 | Billy | 1953-03-19 | America |
| 4 | Paul | 1966-11-06 | Illinois |
+------------+-------+------------+----------+

???

確かにorder by句は正しく指定されているので、

member_idが4から始まるのを期待していたのですが、

結果はmember_idの降順とはならないようです。

では、以下のselect文ではどうなるか試してみます。


select文③

select 

member_id as メンバーID,
first_name as 名前,
birth_date as 誕生日,
address as 住所
from
member
order by
"メンバーID"
desc

select文②との違いは、

asに続く別名の"(ダブルクォーテーション)を外したという点です。

結果は以下のようになります。


実行結果③

+------------+-------+------------+----------+

| メンバーID | 名前 | 誕生日 | 住所 |
+------------+-------+------------+----------+
| 1 | Eric | 1960-10-10 | New York |
| 2 | Pat | 1959-12-13 | Ohio |
| 3 | Billy | 1953-03-19 | America |
| 4 | Paul | 1966-11-06 | Illinois |
+------------+-------+------------+----------+

結果は変わらず、member_idの降順とはなりません。

もうひとつ実験してみたいと思います。


select文④

select 

member_id as メンバーID,
first_name as 名前,
birth_date as 誕生日,
address as 住所
from
member
order by
メンバーID
desc
;

今度は、order by句に指定した別名の"も外しました。

すると、実行結果は以下のようになりました。


実行結果④

+------------+-------+------------+----------+

| メンバーID | 名前 | 誕生日 | 住所 |
+------------+-------+------------+----------+
| 4 | Paul | 1966-11-06 | Illinois |
| 3 | Billy | 1953-03-19 | America |
| 2 | Pat | 1959-12-13 | Ohio |
| 1 | Eric | 1960-10-10 | New York |
+------------+-------+------------+----------+


!?

member_idの降順という、期待通りの結果となりました。

もうひとつだけ試してみたいと思います。


select文⑤

select 

member_id as "メンバーID",
first_name as "名前",
birth_date as "誕生日",
address as "住所"
from
member
order by
メンバーID
desc
;


実行結果⑤

+------------+-------+------------+----------+

| メンバーID | 名前 | 誕生日 | 住所 |
+------------+-------+------------+----------+
| 4 | Paul | 1966-11-06 | Illinois |
| 3 | Billy | 1953-03-19 | America |
| 2 | Pat | 1959-12-13 | Ohio |
| 1 | Eric | 1960-10-10 | New York |
+------------+-------+------------+----------+

結果から察するに、

order by句に別名を指定する際には、ダブルクォーテーションなしの状態で指定しないと、

正しい順序とはならないようです。

(今回は「メンバーID」をorder by句に指定しましたが、代わりに「誕生日」を指定して試してみても良いかもしれません)

MySQLの仕様なのかどうかは定かではありませんが、

いずれにせよ、SQLを書く時に列の別名に日本語を指定するのはあまり得策ではなさそうです。