2015
04/09

meta_queryで小数を含む数値を扱うときの注意

2015.12.09追記
もっといい方法がありましたので別記事にまとめました。

EV183_L

meta_queryは文字列の一致だけでなく、「compare」に等号・不等号や「BETWEEN」という語句を与えることで数値としての条件を設定することができます。
価格範囲による検索や広さなどで扱えそうですね。

query_posts(WP_Queryクラス)でカスタムフィールドを使う

便利な機能ですが、小数を含む数値を扱った際に正常に動作しないということがありました。
原因と対策を紹介します。

ADs

動きそうだけど動かない例

たとえば、「parameter」というカスタムフィールドの値が「2.8以上5.6以下」の記事を抽出する場合を考えてみます。

ドキュメント通りなら以下のようになりますが、これでは意図した記事が抽出されません。

「’type’ => ‘DECIMAL’」のときのSQLがおかしい

上記のアクションフックを適用したとき、記事抽出のためにどのようなSQL文が発行されるかを確認してみると以下のようになります。

CAST(wp_postmeta.meta_value AS DECIMAL)という部分が問題なのですが、「DECIMAL」に属性がセットされていないため、小数点以下を四捨五入してしまいます。

MySQLがインストールされている環境なら以下のようにテストしてみると分かりやすいかと思います。

DECIMALは属性なしの場合、合計10桁で小数点以下はなしの数値に丸められます。

数値型(データ型)のまとめ – [MySQL/SQL] ぺんたん info

アンパック浮動小数点数。CHAR カラムのように動作する。アンパック” とは、その数値が、各桁に 1 文字ずつ使用して文字列として格納されることを意味する。M では、小数点と、負数に使用される ‘-‘ 記号はカウントされない(しかし、これらのためのスペースは確保される)。D が 0 の場合、値は小数点も小数部も持たない。DECIMAL 値の最大範囲は、DOUBLE と同じだが、個々の DECIMAL カラムの実際の範囲は、M と D の値によって制限される。UNSIGNED を指定した場合、負数は使用できない。
D を省略した場合、デフォルトは 0。M を省略した場合、デフォルトは 10
MySQL バージョン 3.23 より前のバージョンでは、M 引数に、符号と小数点に必要なスペースを含める必要がある

解決法

上記のpre_get_postsアクションフックに加え、発行されるSQL文に対するフィルターフックを使ってDECIMAL部分に属性を追加します。

まとめ

この手法は先日作成した2.5ジゲンフォトで、焦点距離や絞りなどの数値検索を実装するために利用しました。
絞り値には小数が含まれるため、検索結果が意図した結果にならずに困っていました。

販売価格をドルで表記するショッピングサイトや平米数を記載する不動産サイトなど、小数を扱うおそれのあるサイトでは気をつけたほうがいいかもしれません。

ADs

Post Comments

メールアドレスが公開されることはありません。

Comments

コメントはまだありません。