言語(PHP他)SQLLaravel
更新日 : 2023年12月11日
投稿日 : 2022年10月25日

【SQL】ORDER BYで特定のレコードを先頭にするソートをいつものクエリビルダでやるとエラーになる【Laravelを例に紹介】

【SQL】ORDER BYで特定のレコードを先頭にするソートをいつものクエリビルダでやるとエラーになる【Laravelを例に紹介】の画像
SELECT id, name FROM person WHERE status=2 ORDER BY id desc;

ID降順でソートしたいとき、このようなSQLになります。

では、IDが3のデータを必ず先頭にして、その後はID降順のソートにするときはどのようなSQLになるでしょうか?

SQL文は

SELECT id, name FROM person WHERE status=2 ORDER BY id=3 desc, id desc;

となります。

これをLaravelのクエリビルダで書くにはどうしたらいいでしょうか?

ここではオープンソースの梅子CMSで使っているプログラムを例に紹介します。

LaravelクエリビルダのよくあるSQL

梅子CMSのソースの一部、

app/Models/Article.phpのgetPublishList

は以下のようになっています。

$table = DB::table($this->table);
$data = $table
   ->leftjoin('users as user', 'user.id', '=', 'article.user_id')
   ->leftjoin('save_file as s_file', 's_file.id', '=', 'article.icatch')
   ->select($cols)
   ->where('status', config('umekoset.status_publish'))
   ->where('article.publish_at', '<=', $now)
   ->orderBy('article.publish_at', 'desc')
   ->orderBy('article.id', 'asc')
   ->limit($num)
   ->get();

return $data;

こんな感じになっています。

通常、LaravelでORDER BYを使うときはorderByのクエリビルダを使います。

では、ORDER文を少し変更して「id=3が先頭に来る」ように書くとどうなるでしょうか。

エラーが起きるLaravelクエリビルダのSQL

id=3が先頭にくるようにすると、こんな書き方をしたくなると思います。

$table = DB::table($this->table);
$data = $table
   ->leftjoin('users as user', 'user.id', '=', 'article.user_id')
   ->leftjoin('save_file as s_file', 's_file.id', '=', 'article.icatch')
   ->select($cols)
   ->where('article.publish_at', '<=', $now)
   ->orderBy('article.id=3', 'desc')
   ->limit($num)
   ->get();

return $data;

※便宜上、ステータス条件のwhereを外しています

getPublishListの変更(orderBy)

これを実行すると、残念ながらSQLエラーになります。

実行エラー画面(SQLエラー)

Unknown Column ~~~~ in ‘order clause’

そんなカラム知りませんけど?と言われています。

書き方としてはそこまで間違っていないように思えますが、どうしてエラーになってしまうのでしょうか?

原因:ORDER BYの第一引数まるごとにバックスラッシュをかけるから

エラーとなった部分をよく見てみると、「ORDER BY ‘article’.’id=3’ desc」となっています。

実行エラー画面ハイライト(SQLエラー)

第一引数をバックスラッシュで囲んでしまうため、「id=3」という名前のカラム名を降順、と書かれてしまうのです。

id=3というカラム名は当然ながらありませんので、実行エラーになります。

解決方法:orderByRawでORDER句を直接書けばOK

「orderByRaw」を使ってORDER文を直接書くとエラーが起きなくなります。

$table = DB::table($this->table);
$data = $table
    ->leftjoin('users as user', 'user.id', '=', 'article.user_id')
    ->leftjoin('save_file as s_file', 's_file.id', '=', 'article.icatch')
    ->select($cols)
    ->where('article.publish_at', '<=', $now)
    ->orderByRaw('article.id=3 desc, article.id=1 desc, id desc')
    ->limit($num)
    ->get();

return $data;
getPublishListの変更(orderByRaw)

これを実行すると、正常に画面が表示されます。

指定ソート順で並べた結果

まとめ

SELECT id, name FROM person WHERE status=2 ORDER BY id=3 desc, id desc;

のような、id=3のデータを必ず先頭にしてその後はID降順のソートにするとき、Laravelでよく使うクエリビルダで書くとSQLエラーになります。

これを防ぐには、orderではなくorderByRawのクエリビルダを使い、ORDER BY句を直接書くことで解決できます。

その他フレームワークでも同じことが起こり得る-ZendFrameworkで直面しました

今回はLaravelで紹介しましたが、その他フレームワークでも同様のことが起こる可能性が高いと思います。

筆者はZendFrameworkで同様の問題に直面しました。

もし「正しい書き方のはずなのにSQLエラーが出る」と思ったら、クエリビルダで自動付与されるバックスラッシュの位置を疑ってみてください。

梅子-Umeko- CMS

梅子-Umeko-はウェブページを管理するCMSアプリケーションです。

Naho Osadaによって開発されました。

梅子は主にブログのような、「更新頻度がそれなりに高い」ものに向いています。

フリーランスの案件探しはエミリーエンジニア※広告

毎日仕事をしながらも次の案件を気にしなければならない…フリーランスの宿命です。

そんな大変な案件探しは【エミリーエンジニア】のエージェントに助けてもらってはいかがでしょうか。

▼ 登録はここから ▼

【エミリーエンジニア】

  • 月額60~80万円の高額案件中心
  • 15年以上の信頼と実績があるから、プライム案件を受注できる
  • フルリモート案件が90%以上
です。

専属のキャリアアドバイザリーコンサルタントに色々と相談もできますよ。

エンジニアの転職はキャリアネクスト※広告

今の職場で頑張っても収入アップは見込めない…

エンジニア転職の【キャリアネクスト】で転職で収入アップを目指してみてはいかがでしょう?

▼ 登録はここから ▼

【キャリアネクスト】なら

  • エンジニアのキャリア支援を始めて10年以上!
  • 大手からベンチャー、スタートアップまで幅広い
  • 理想のキャリアプランから最適と考える企業様だけをご紹介
  • 応募書類の添削や企業との連絡代行などのフォローあり
  • 不安なことは専任のアドバイザーにすぐ相談
など、仕事をしながら転職活動する上で大変なことをかなりお任せできちゃいます!

PR

※本サイトはアフィリエイトプログラムを利用して商品を紹介しています。