スポンサーリンク

「MySQL」「order by」が機能しない時がある

原因

エイリアスを理解していなかった。
エイリアスは単純に別名と思っていただけだった。
効率とソースコードの合理化からエイリアス名を実カラム名と同名にしていた。(ただし理由は後述)

SELECT SUM(column_a) as column_a FROM table as t1
WHERE t1.column_a = 1
GROUP BY t1.column_a
ORDER BY t1.column_a DESC ←これが原因

カラムエイリアスは抽出結果の表に別名を付与するもの。
テーブルエイリアスは抽出元のテーブルに付与するもの。
なので「ORDER BY」にはテーブルエイリアスを付与すると結果の表でソートするのではなく、抽出元のテーブルをソートしてしまっており、結果の表はソートされていないので「ORDER BY」句が機能しないまたは違うソート結果になる。

対処

エイリアスを理解する。
必要のないエイリアスは使わない。

上記のSQLの場合
WHERE句には抽出元となるテーブルに対してなのでエイリアスをつけても良い。
GROUP BY句にも抽出元となるテーブルに対してなのでエイリアスをつけても良い。
ORDER BY句は結果の表に対してするものなのでエイリアスをつけてはいけない。

なぜエイリアスを実名カラム名と同名にしたのか?

同名にすることでソート条件(昇順降順)をHTTPの部分と共通化しソースコードを合理化している。

<!-- HTTP、ソート条件をリンクにして遷移時に照準降順を切り替える -->
<a href="index.php?sort_col="{{ $sort_col[各エイリアス] }}&sort_order="{{ 昇順または降順の値 }}">

// phpではエイリアスを配列にしてSQLにforeachでループして割り当てている。
// リンクで表現する列が増えてもエイリアス配列を追加するだけで良いロジックになる。

そもそもの原因

久しぶりにSQLを触った・・・。
いつもは結合や副問い合わせでしかエイリアスは使わない。

# 副問い合わせでの以下のようなものと混同してしまった。
(SELECT SUM(column_a) as column_a FROM table
WHERE t1.column_a = 1)  as t1

参照するテーブルと結果の表のエイリアスの命名規則を分けるべきかなと思いました。
テーブルは「t1」等、結果表は「r1」(result)等とか。

感想

厄介なことにそれっぽく動くんで気づきにくいんですよね。
今後は意識してエイリアスをつけようと思います。