シス、再び受託でDB屋さんと流浪する人のブログです。Oracleいやー、知らないって怖いね。なんだこのキモいSQLは、って思ってしまったけど、調べているウチに、これちゃんとSQL構文に則ってる!こちらが間違ってた!って事がわかっていきました。知らなかった所から勢いで書いていたのを、そのままにしてみました。BYって、その後にカラム(およびそのエイリアス)を並べてソート順として使用するわけですが、MySQL案件のお仕事の中で偶然こんなものを見つけて、絵に描いたような二度見リアクションしました。リファレンスマニュアルの中から見つけ出すことができませんでした。(2)の構文については、公式ドキュメントのコメント欄から見つけ出したものです。BYの中でCASE句を切ってソート指定列を変えるとかは、あくまで列指定の切り替えなので理解の範囲内でした。RAND()とか使うのは知っていますが、こういった、ソートオーダーの指定で直値を指定する形のものは初めて見ました。いうわけで、少し調べてみました。いつものように、試してみる。5.6(5.6.31)で試しています。この時点での感想は「わけがわからないよ。救世主yoku0825先生現る。FIELD関数は、調べた限りMySQLにしか存在しない関数で、「第一引数が、第二引数以降に列挙したなかの何番目に現れるかを返す」関数です。SQLという、行による集合演算メインの処理系において、なんでこんな関数が存在しているんだ?という印象がありますが、そこは後々その有難味がわかってくるのでしょう。yoku0825さんのSQL文の書き換え例で、やっと意味が分かりました。WARNINGSでSQL解析・書き換え結果がみえるわけですが、残念ながら?書き換えは行われず元のSQL文のままでした。sec)このあたりで、最初「なにこれキモい」って言ってた自分を思い出して、顔が真っ赤になるわけです。FIELD」に関する情報に倣うと、この直値指定もまた、「列名=直値」という「評価式の結果」でソートをしているのであろうと推測されます。DESC;と書き換えることができます。5」という評価式の真(1)偽(0)でソートとなり、偽の集団に中においては、その表示順は保証されません。「=」以外の色々な演算子でも、式として成立していれば、同じことができます。構文の「expr」に当てはまればなんでもあり、と。MySQL方言を超えてまず、FIELD関数がMySQL固有のものです。Server/Access/PostgreSQL/MySQL/ANSI)なSQLリファレンス本を幾つか漁ってみましたが、同等の機能を持つ関数を実装している他のRDBMSは見つかりませんでした。これを多くのDBMSで通用しそうなSQLに置き換えるとすると、「CASE」がわかりやすいでしょう。sec)このように、CASEで置き換えができました。これをOracleにぶん投げてみます。e10行が選択されました。310行が選択されました。BYの中でのCASE、および、SELECT内でのCASE処理結果のエイリアス、双方とも同じように動きました。やったね!「列名=直値」の方ですが、Oracleでそのままいけるかなーと思いましたが、残念ながら構文エラーです。BYにおいても、SELECT側においてエイリアス指定の形にしても、構文エラーです。THENを1つだけ、あとはELSEに流すようにしましょう。行)CASEはもちろん、「列名=直値」も通ったよ!ただし、評価結果は「t(true)」「f(false)」で帰ってきます。BY~には、関数や評価式が指定できる。・その延長で、MySQLのFIELD関数が使えるので、任意の出力順を指定できる。FIELDという構文じゃないよ)・MySQL以外の場合、CASE句に書き換えることが可能。SQLの仕様にCASEを取り込んだ人は神。12日目の記事です...2016-11-02MySQLで複合列PKなテーブルに対するWHERE条件でINを使うと、実行計画が変わる?何言っているかわかんねえよ。思うので、事例で語る。読者になる@atsuizoをフォローRSSFeedlyへの登録はこちらからFeedly以外への登録は、お手数ですが以下URLを登録お願いします。MySQL注目記事はてなブログをはじめよう!atsuizoさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。