本文へ移動

WP_Query解説

カテゴリー・タグをAND・ORで絞る方法
|tax_query

「カテゴリーAとタグBの両方が付いた投稿だけを出したい」「どちらかが付いていれば出したい」。この違いを決めるのがtax_queryのrelationです。先に日本語で「両方」か「どちらか」を決め、AND / ORの位置と結果を最小例で確認します。

Huddly Huddly 投稿日: 2026年9月25日 読了目安: 4分

「両方」ならAND、「どちらか」ならOR

tax_queryのrelationは、複数の条件グループをどうつなぐかを決める指定です。relation => ‘AND’ は「すべての条件を満たす投稿」、relation => ‘OR’ は「どれか1つでも条件を満たす投稿」を返します。

relationはtax_queryの中に条件が2つ以上あるときに意味を持ちます。この記事では、同じ2条件をANDとORで比べ、operatorやinclude_childrenとの違いも整理します。

まず「両方」か「どちらか」を日本語で決める

1条件の配列から確認したい場合はtax_queryの基本構造へ戻ります。カテゴリーだけ結果が合わない場合は、relationを増やす前にカテゴリー絞り込みが効かない原因を確認してください。

relationは複数の分類条件を「全部必要」と見るか、「どれかでよい」と見るかを指定します。

relation意味返る投稿のイメージ
ANDすべての条件を満たす条件が増えるほど結果は絞られやすい
ORどれか1つでも条件を満たす条件が増えるほど結果は広がりやすい
ANDとORは、結果件数ではなく「すべて一致」か「どれか一致」かという要件で選びます。 relationは、複数のtax_query条件をつなぐための指定です。1つの条件だけを見ている時は、まずrelationよりtaxonomy / field / termsを確認します。

ANDはすべての条件を満たす投稿を返す

次は「お知らせカテゴリー(ID2)、かつ検証用タグ(ID7)」の例です。結果の違いを追いやすいように、比較対象を次の5投稿に限定します。投稿IDとタームIDは別の数字で、どちらもサイト固有です。

投稿IDカテゴリー検証用タグ(ID7)
10お知らせ(ID2)あり
11イベント案内(ID3)あり
12制作ノート(ID4)あり
26お知らせ(ID2)なし
82別のお知らせ(ID12)なし

クラシック子テーマのtemplate-parts/tax-comparison.phpへ保存し、表示したいテンプレートのメインループ内でthe_post()の後にget_template_part( ‘template-parts/tax-comparison’ );を呼びます。投稿本文やfunctions.phpの直下に貼るコードではありません。確認後は呼び出しと確認用ファイルを撤去します。

現在のWP Query Builder実画面では、詳細モードから「post / publish / 6」「post__in: 26,12,11,10,82」「orderby: post__in」、Tax Queryへ「category / term_id / 2 / include_children=false」と「post_tag / term_id / 7」を入力し、relationをAND、ignore_sticky_postsをtrue、自動最適化をオフにしました。そこで生成された次の$argsは編集せず使用しています。

クラシックテーマのテンプレート(またはテンプレートパーツ)で、一覧を表示したい位置に置く例です。投稿本文やfunctions.phpへ、そのまま貼るコードではありません。

PHPtemplate-parts/tax-comparison.php比較対象5投稿からカテゴリー2とタグ7の両方に合う投稿を表示する
<?php$args = array(    'post_type' => 'post',    'post_status' => 'publish',    'posts_per_page' => 6,    'orderby' => 'post__in',    'post__in' => array(        26,        12,        11,        10,        82    ),    'tax_query' => array(        'relation' => 'AND',        array(            'taxonomy' => 'category',            'field' => 'term_id',            'operator' => 'IN',            'include_children' => false,            'terms' => 2        ),        array(            'taxonomy' => 'post_tag',            'field' => 'term_id',            'operator' => 'IN',            'terms' => 7        )    ),    'ignore_sticky_posts' => true); $query = new WP_Query( $args ); if ( $query->have_posts() ) {   echo '<ul>';    while ( $query->have_posts() ) {      $query->the_post();       printf(         '<li><a href="%s">%s</a>(ID: %d)</li>',         esc_url( get_permalink() ),         esc_html( get_the_title() ),         get_the_ID()      );   }    echo '</ul>';} else {   echo '<p>条件に一致する投稿はありませんでした。</p>';} wp_reset_postdata();

Builderが生成したのは$argsまでです。続くWP_Query、表示ループ、0件時の文、投稿IDの表示、エスケープ、wp_reset_postdata()は用途に合わせて手動で追加しています。orderby => ‘post__in’により、条件に合った投稿は比較用のID列の順で表示します。

relationは各条件の中ではなく、2つの条件を包むtax_query直下に置きます。カテゴリーはinclude_children => falseとして、指定したターム自体の付与を見ます。

post__inは比較対象を固定するための指定です。全投稿から絞り込むなら行ごと削除し、空配列を「対象なし」の意味では使わないでください。
カテゴリー2とタグ7をANDで絞り込み投稿ID10だけを表示するサイト
ANDの表示例両方に当てはまるID10だけ

比較対象5投稿のうち、お知らせカテゴリーと検証用タグの両方が付いているのはID10です。

分類条件を切り替える作業は、本番と分けた環境で行います。サーバー上に試す場所を用意する場合は、XserverのPHP対応やバックアップ条件も確認できます。

ORはどれかの条件を満たす投稿を返す

同じ5投稿・同じ2条件で、relationだけをORへ変えます。最初のコードの$args定義直後、$query = new WP_Query( $args );より前へ次の1行を置いてください。取得・表示・リセットの部分は変えません。

引数や処理の一部分だけを示した例です。このまま単独で貼らず、テンプレート内のWP_Queryとループへ組み込んでください。

PHPtaxonomy-or-args.php最初の$argsのrelationだけをORへ変え、同じ表示ループへ渡す
$args['tax_query']['relation'] = 'OR';

結果はID26・12・11・10の4件です。両方に属するID10も、1件として含まれます。「お知らせの中でも検証用タグ付きだけ」ならAND、「お知らせも検証用タグ付きもまとめる」ならORです。

同じカテゴリー2とタグ7の条件をORにして投稿ID26、12、11、10を表示したサイト
ORの表示例どちらかに当てはまる4件

カテゴリーだけのID26、タグだけのID12・11、両方のID10が表示されます。両方ないID82は含まれません。

条件表示される投稿ID読み取り方
カテゴリー2だけ26・10条件Aの対象
タグ7だけ12・11・10条件Bの対象
A AND B10両方の対象に共通する投稿
A OR B26・12・11・10どちらかの対象に含まれる投稿

relationのANDとoperatorのANDは別物

relation => ‘AND’は条件グループ同士、operator => ‘AND’は1つの条件内にある複数termsの判定です。

include_childrenは階層タクソノミーで子タームを含めるかを決めます。

指定置く場所何を決めるか
relationtax_queryまたは入れ子グループの直下複数の条件配列をAND / ORでつなぐ
operator各条件配列の内側1条件内でtermsをどう判定するか決める
include_children階層taxonomyの条件内子タームを検索範囲へ含めるか決める

たとえば、2つのタクソノミー条件をどちらも満たしたいなら、外側のrelationをANDにします。1つのtaxonomy内で複数termsの扱いを変えたい場合は、条件内のoperatorを確認します。

既存コードは、外側のrelation、各条件のoperator、include_childrenの順に読むと整理しやすくなります。

次は「お知らせ(ID2)とイベント案内(ID3)の両カテゴリーが付いた投稿」を探す差分です。最初の$args定義後、new WP_Queryの前に置きます。ORの差分とは同時に貼らず、1例ずつ比べてください。

引数や処理の一部分だけを示した例です。このまま単独で貼らず、テンプレート内のWP_Queryとループへ組み込んでください。

PHPtaxonomy-operator-args.php1つのcategory条件のtermsをoperator ANDで判定する
$args['tax_query'] = [   [      'taxonomy' => 'category',      'field'    => 'term_id',      'terms'    => [ 2, 3 ],      'operator' => 'AND',      'include_children' => false,   ],];

比較対象5投稿には両カテゴリーが付いた投稿がないため、結果は0件です。operatorだけをINへ変えると、どちらかのカテゴリーが付いたID26・11・10の3件になります。relationをORにしても、この1条件の中のoperator => ‘AND’がINへ変わるわけではありません。

relationとoperatorの役割が分かったら、WP Query Builderで同じ2条件を組み立てられます。生成したtax_queryを最初の$argsへ渡し、対象の投稿IDが一致するか比べます。

AND・ORの取得条件を組み立てる

taxonomy、field、terms、relationから$argsを作れます。比較対象のpost__inや表示ループ、入れ子のグループは、この記事の例と合わせて確認してください。

複雑な条件はネストで表現する

入れ子にすると「お知らせカテゴリー、または(検証用タグかつイベント案内カテゴリー)」も表せます。最初の$args定義後、new WP_Queryの前に次の差分を置き、同じ表示ループへ渡します。

引数や処理の一部分だけを示した例です。このまま単独で貼らず、テンプレート内のWP_Queryとループへ組み込んでください。

PHPnested-tax-args.phpお知らせ、または検証用タグかつイベント案内を同じ$argsへ指定する
$args['tax_query'] = [      'relation' => 'OR',      [         'taxonomy' => 'category',         'field'    => 'term_id',         'terms'    => [ 2 ],         'include_children' => false,      ],      [         'relation' => 'AND',         [            'taxonomy' => 'post_tag',            'field'    => 'term_id',            'terms'    => [ 7 ],         ],         [            'taxonomy' => 'category',            'field'    => 'term_id',            'terms'    => [ 3 ],            'include_children' => false,         ],      ],];
外側のORは「お知らせ」と内側のANDグループをつなぎ、内側のANDは「タグとイベント案内の両方」を1つのまとまりとして判定します。

お知らせのID26・10に、タグとイベント案内の両方が付いたID11が加わり、結果はID26・11・10の3件です。タグだけのID12は内側のANDに合わないため外れます。

実務では、先に日本語で条件を書く

複雑なtax_queryを書く前に、「Aか、またはBかつC」のように日本語で条件を書き出すと、AND / ORの位置を間違えにくくなります。条件を1行で説明できる状態にしてからコード化すると、後で配列を読み直しやすくなります。

結果が合わないときに確認する順番

結果が合わない時はrelationだけでなく、taxonomy、field、terms、投稿へのターム付与を確認します。slugとterm ID、登録名と表示名の取り違えにも注意してください。

確認の順番

  1. 1
    tax_queryを1条件だけにして結果が返るか見る
  2. 2
    taxonomy名が登録名と一致しているか確認する
  3. 3
    fieldがslug / term_id / nameのどれか確認する
  4. 4
    termsに実在する値を入れているか確認する
  5. 5
    最後にrelationをAND / ORで切り替えて件数の変化を見る

この順番で、条件Aだけ、条件Bだけ、AND、ORの4通りを比べます。条件AやBだけでも0件なら、relationではなくtaxonomy、field、terms、投稿へのターム付与を見直します。空の条件配列を動的に作っていないかも確認してください。

WP Query Builderでは、カテゴリーやタグなどの条件を画面で選び、生成される$argsと条件の意味を日本語で確認できます。ANDとORの位置が分かりにくいときは、まず2条件だけを設定して、画面の説明と生成コードを見比べてください。

tax_queryのrelationとネストの公式資料

指定方法とネスト例はWP_Query、条件の検証やSQL組み立てはWP_Tax_Queryの公式資料で確認できます。

公式リンク

公式ドキュメント

最後に確認したいこと

  • relationは複数のtax_query条件をつなぐ指定だと理解している
  • ANDはすべて満たす、ORはどれかを満たすと説明できる
  • relationとoperatorのANDを混同していない
  • 結果が合わないときは1条件ずつ減らして確認できる
  • 複雑な条件は先に日本語で書き出してからコード化できる
WP Query BuilderBuilderで条件を組み直す条件を選び、WP_Queryのコードを画面で作れます。Builderでクエリを作る

この記事を書いた人

Huddly

Web制作 / フロントエンドエンジニア

WordPressとフロントエンド実装で迷いやすい点を、公式情報と検証結果を分けながら、初学者にも追いやすい順序で整理しています。

この記事の検証情報

検証環境

WordPress
7.1.4
PHP
8.3.36
テーマ
wpq-media + DDEV
対象
カスタム投稿 / taxonomy / meta_query

更新履歴

  • 2026年9月25日 初回公開

この記事を活用する

あとで見返す・共有する

お気に入りに保存できます。役に立ったポイントは、いいねや共有で教えてください。

任意のご支援 役に立ったときだけ、活動を応援できます OFUSEはサイト・記事制作に使います。支援の有無で、読める内容や使える機能は変わりません。