数値順にならない時は、meta_keyと保存値から確認する
orderby=meta_value_num が効かない時は、まず meta_key と、対象値が数値として扱える形で保存されているかを確認します。
よくある原因は、meta_key の指定漏れ、単位やカンマを含む保存値、逆向きの order、meta_query による対象除外、複数メタ条件で並べ替え対象が曖昧なことです。条件を1つのメタキーと3件程度に減らして切り分けます。
「2より10が先に出る」症状を切り分ける
まずorderbyとorderの基本で並び替え対象と昇順・降順を確認します。そのうえで投稿メタの条件も使っている場合は、meta_queryの基本と役割を混ぜていないかを見てください。
meta_value_numは、価格や点数などのメタ値を数値として並べるorderbyの指定です。ただし、並べ替えるmeta_key、保存値、order、絞り込み条件のどれかが合わないと、期待した順番にはなりません。
| 症状 | 最初に疑う原因 | 確認する場所 |
|---|---|---|
| 10より2が後ろに来るなど、数字順に見えない | 保存値が数値として扱えない、またはmeta_valueで並べている | orderby、保存値、meta_key |
| 並び替えたい投稿が一部出ない | meta_keyが存在しない投稿が除外されている、またはmeta_query条件が強い | カスタムフィールドの有無、meta_query |
| 新しい順や日付順のまま変わらない | orderbyが上書きされている、または指定位置が違う | WP_Queryの$args、pre_get_posts |
| 昇順と降順が逆に見える | orderの指定が意図と逆 | orderのASC / DESC |
| 複数条件で思った値を見てくれない | どのmeta_query句で並べるかが曖昧 | meta_queryの構造、名前付き句 |
よくある原因一覧
保存値が1,200や10点なら、コード上は数字に見えても数値順には向きません。また、meta_queryで投稿自体が除外されている場合もあるため、取得対象と並び順を分けて見ます。
先に疑う順番
- 1orderbyだけでなくmeta_keyが指定されているか確認する
- 2保存値が数値だけになっているか確認する
- 3orderがASCかDESCか確認する
- 4meta_queryを一度外して並び順だけを試す
- 5複数のmeta_query句で、どのメタ値を並べるのか確認する
- 6実際に取得された投稿IDとメタ値を出して確認する
まずは最小例で数値順になるか確認する
ここでは、公開済みのworks投稿3件に、priceとして60000、120000、80000が保存されている例を使います。クラシック子テーマのtemplate-parts/price-list.phpへ保存し、表示したいテンプレートのメインループ内でthe_post()の後にget_template_part( ‘template-parts/price-list’ );を呼んでください。投稿本文やfunctions.phpの直下に貼るコードではありません。
worksとpriceは、自分の投稿タイプの登録キーと保存キーへ置き換えます。通常投稿ならpost_typeはpostです。確認用として追加した場合は、終了後に呼び出しとファイルを撤去してください。
現在のWP Query Builderでは、詳細設定で「custom / works / publish / 5 / ASC / meta_value_num」を選び、Meta Queryへ「key: price / value: 空欄 / compare: EXISTS / type: default CHAR」を入力しました。自動高速化はオフです。次の$argsは、その実画面で生成された内容を変更せずに使っています。
クラシックテーマのテンプレート(またはテンプレートパーツ)で、一覧を表示したい位置に置く例です。投稿本文やfunctions.phpへ、そのまま貼るコードではありません。
<?php$args = array( 'post_type' => 'works', 'post_status' => 'publish', 'posts_per_page' => 5, 'order' => 'ASC', 'orderby' => 'meta_value_num', 'meta_query' => array( array( 'key' => 'price', 'compare' => 'EXISTS' ) ), 'meta_key' => 'price'); $price_query = new WP_Query( $args ); if ( $price_query->have_posts() ) { echo '<ul>'; while ( $price_query->have_posts() ) { $price_query->the_post(); $price = get_post_meta( get_the_ID(), 'price', true ); printf( '<li><a href="%s">%s</a>(ID: %d / price: %s)</li>', esc_url( get_permalink() ), esc_html( get_the_title() ), get_the_ID(), esc_html( $price ) ); } echo '</ul>';} else { echo '<p>料金が保存された公開済みの情報はありません。</p>';} wp_reset_postdata();Builderが生成したのは$argsまでです。その後のnew WP_Query()、料金とIDの表示、0件時の文言、wp_reset_postdata()は、結果を確かめるために手動で追加しています。
meta_keyで基準を、orderbyで数値順を、orderで向きを指定します。Meta QueryのEXISTSはpriceが保存された投稿だけを対象にする条件です。この最小例で並ぶなら、実際のコードに追加した別のmeta_query、orderbyを変える処理、保存値のばらつきを調べます。 同じ料金の投稿同士の順番は、このBuilder生成コードだけでは固定していません。
文字列順と数値順で同じ3件を見比べる
本文コードのorderbyをmeta_valueへ変えると、同じ料金でも120000・60000・80000の順になります。先頭の文字から比べるため、桁数の大きい120000が先に来る例です。meta_value_numへ戻すと60000・80000・120000の順になります。

同じ3投稿をmeta_value・ASCで表示。ID17(120000)→16(60000)→18(80000)となり、数の大小ではなく文字列として並びます。

本文コードの結果はID16・18・17。保存値60000・80000・120000の昇順です。
保存値や並び順を調べる作業は、本番と分けた環境で行います。サーバー上にも試す場所が必要なら、XserverのPHP対応やバックアップ条件を確認できます。
数値順にならない原因を順に確認する
最小例で並び順を確認できたら、meta_key、保存値、order、絞り込み条件、複数メタ、外部処理の順に実際のコードを確認します。
確認1:meta_keyを指定しているか
orderbyとorderだけでは、どのメタ値を使うかが分かりません。単一のメタキーで並べる最小例では、meta_key、orderby => ‘meta_value_num’、orderをセットで確認します。 大きい値を先にするならDESC、小さい値を先にするならASCです。上のBuilderではMeta Queryへpriceを入力したため、生成コードにもmeta_key => ‘price’が加わっています。
確認2:保存値が数値だけになっているか
meta_value_num を使っても、保存値そのものが数値として扱いにくい形なら、期待通りの結果にならないことがあります。表示上は「1,200円」でも、データベースに保存されている値が 1200 なのか、1,200 なのか、1200円 なのかで意味が変わります。
WordPress本体のmeta_value_numは、SQLでメタ値に+0して数値へ変換して並べます。数値ではない文字を含む値は、意図しない数へ変換される可能性があるため、「画面では数字に見える」だけで判断しないでください。
単一のメタキーならmeta_keyとmeta_value_numが簡潔です。整数をmeta_valueで並べる別の方法として、meta_type => ‘NUMERIC’で型を明示できます。複数のメタ条件では、後述する名前付き句を参照すると役割を分けやすくなります。
WordPressのNUMERICは内部ではSIGNED(整数)へ変換されます。小数を残す必要がある場合は同じ指定を流用せず、たとえばDECIMAL(12,2)のように必要な桁数・小数桁数を指定します。meta_value_numの+0と、整数へ変換するNUMERICを同じ処理だとは考えないでください。
入力画面の表示とデータベースの保存値は同じとは限らないため、実際の値を確認します。| 保存値の例 | 数値として扱えるか | 確認ポイント |
|---|---|---|
| 1200 | 扱える | 整数の文字列としてis_numeric()がtrue |
| -15 | 扱える | 負数を要件として許可するか |
| 12.5 | 扱える | 小数の丸め方を確認する |
| 001200 | 扱えるが要確認 | ゼロ埋めを意味として残すか |
| 1,200 | そのままでは不適切 | カンマを保存値から除く |
| 1200円 | そのままでは不適切 | 単位は表示時に付ける |
| 空文字 | 要件次第 | 0と未入力を区別する |
| キー未保存 | 並び替え対象外になり得る | metadata_exists()で確認する |
実際のメタ値を表示して確認する
次のコードは、対象投稿IDを1つ決め、priceの保存状態と値が数値として扱えるかを確認する例です。template-parts/debug-price.phpへ保存し、ローカルのテンプレートからget_template_part( ‘template-parts/debug-price’ );を一時的に呼びます。例のID17は自分の投稿へ置き換え、終了後は呼び出しとファイルを撤去してください。
原因を切り分けるための一時的な確認コードです。ローカルなどの検証環境だけで使い、確認後は削除してください。
<?php$post_id = 17;$meta_key = 'price';$price = get_post_meta( $post_id, $meta_key, true ); echo '<pre>';echo esc_html( var_export( [ 'post_id' => $post_id, 'exists' => metadata_exists( 'post', $post_id, $meta_key ), 'value' => $price, 'is_numeric' => is_numeric( $price ),], true ) );echo '</pre>';metadata_exists()でキーの有無、get_post_meta()で保存値、is_numeric()でPHPから見て数値として扱える文字列かを確認します。false、空文字、1200円などが出た場合は、並び順の指定より先に保存設計を見直してください。
この表示例のID17はexistsがtrue、valueが文字列120000、is_numericがtrueです。値はHTMLとして実行されないようエスケープしていますが、公開してよい情報だけを扱ってください。PHPで数値と判定できることと、SQL側の変換が要件どおりであることは別に確認します。
確認3:orderの向きが意図と合っているか
orderbyは基準、orderは向きです。数値ではASCが小さい順、DESCが大きい順です。
| 指定 | 並び方 | 使う場面の例 |
|---|---|---|
| order => ASC | 小さい値から大きい値へ | 価格の安い順、番号の若い順 |
| order => DESC | 大きい値から小さい値へ | 評価数の多い順、スコアの高い順 |
本文コードのorderだけをDESCへ変えると、ID17・18・16(120000・80000・60000)の順です。後述するorderbyを配列にした例では、全体のorderではなく、配列の各キーへ書いた向きを変更します。
確認4:meta_queryが対象投稿を落としていないか
meta_queryと一緒に使っている場合は、並び順の問題に見えて、実際には絞り込み条件で投稿が除外されていることがあります。取得件数が減った時は、並び順を変える前にmeta_queryで対象外になっていないかを確認します。 たとえば、priceで並べたいのに、別のarea条件で対象投稿が消えているケースです。
まずmeta_queryを外し、meta_key、orderby、orderだけに戻します。並んだらmeta_queryを1条件ずつ戻します。
絞り込みと数値順を組み合わせる例
次は、地域の保存値がtokyoの投稿だけに絞る差分です。最初の$args定義直後、$price_query = new WP_Query( $args );より前へ置き、同じ表示ループへ渡します。
引数や処理の一部分だけを示した例です。このまま単独で貼らず、テンプレート内のWP_Queryとループへ組み込んでください。
$args['meta_query'] = [ [ 'key' => 'area', 'value' => 'tokyo', 'compare' => '=', ],];結果はID18・17(80000・120000)の2件です。ID16の地域はosakaなので外れます。areaは絞り込み、priceは並べ替えです。投稿が減った理由を、数値順の不具合と混同しないようにします。
料金の数値順と地域の絞り込みを分けられたら、WP Query Builderで同じ取得条件を組み立てられます。生成した$argsを表示ループへ渡し、料金と投稿IDの順番を見比べます。
数値順と絞り込みの条件を作る
meta_key、orderby、order、meta_queryから$argsを作れます。保存値の整備と、小数を扱う型の選択は、実際のデータで別に確認してください。
確認5:複数のメタ条件でどの値を並べるか曖昧になっていないか
単純な場合はmeta_keyとmeta_value_numで十分です。複数のメタ条件がある場合は、句に名前を付け、親クエリのorderbyから参照すると基準を明示できます。
名前付きのmeta_query句で並べ替える例
次は同じ「地域tokyoの中で料金順」を、price_clauseという名前付きの句で書く例です。最初の$args配列を丸ごと置き換え、new WP_Query以降はそのまま使います。直前の地域差分を追加で貼る必要はありません。
引数や処理の一部分だけを示した例です。このまま単独で貼らず、テンプレート内のWP_Queryとループへ組み込んでください。
$args = [ 'post_type' => 'works', 'post_status' => 'publish', 'posts_per_page' => 5, 'meta_query' => [ 'relation' => 'AND', 'price_clause' => [ 'key' => 'price', 'compare' => 'EXISTS', 'type' => 'NUMERIC', ], [ 'key' => 'area', 'value' => 'tokyo', 'compare' => '=', ], ], 'orderby' => [ 'price_clause' => 'ASC', 'ID' => 'ASC', ],];この整数料金の例でも、結果はID18・17の2件です。price_clauseが並べ替えの基準、areaが絞り込みです。同額ではIDの小さい順になります。EXISTSはキーの存在確認なので、空文字や数値でない保存値まで正常値として保証する条件ではありません。
確認6:別の処理でorderbyが上書きされていないか
テーマやプラグインの中で pre_get_posts などを使っている場合、そこで orderby や meta_key が上書きされていることがあります。自分が書いた $args は正しく見えるのに、実際の表示が変わらない時は、別の場所でクエリが変更されていないか確認します。
特にアーカイブページや検索結果ページでは、メインクエリを変更する処理が入っていることがあります。個別に new WP_Query() しているつもりでも、テンプレートの別の箇所やプラグイン側の処理が影響している可能性はあります。
対象テンプレートの$args、functions.phpなどのpre_get_posts、並び順を変えるプラグインを検索します。最小構成だけ正しく並ぶなら周辺処理、最小構成も崩れるならmeta_key、保存値、orderを見直します。
カスタムフィールドの並べ替えに使う公式資料
並べ替えはWP_Query、typeや名前付き句はWP_Meta_Query、保存値はget_post_meta()とmetadata_exists()の公式資料で確認します。
公式リンク
公式ドキュメント
最後に確認したいこと
まずpost_type、meta_key、orderby、orderだけで3〜5件を並べ、保存値、meta_query、複数条件、上書き処理を順に戻します。投稿IDとメタ値も記録して、見た目ではなく結果で判断してください。
数値順の最終判断
- 並べ替え対象の保存値が数値だけで統一されている
- 欠損値や同値の投稿をどう並べるか決めた
- meta_queryの絞り込みと並び替え対象を混同していない
- 二次ソートを含む期待する投稿ID順を記録した
- 別フックやプラグインを戻した後も同じ順になる
この記事の検証情報
検証環境
- WordPress
- 7.1.4
- PHP
- 8.3.36
- テーマ
- wpq-media + DDEV
- 対象
- カスタム投稿 / taxonomy / meta_query
更新履歴
- 2026年9月29日 初回公開
この記事を活用する
あとで見返す・共有する
お気に入りに保存できます。役に立ったポイントは、いいねや共有で教えてください。


