カテゴリ、タグ、カスタムタクソノミーで絞り込む


たとえば「選択」でタグづけされた公開「リスト」投稿で引用されている「本」を一覧したいとします。これは投稿に関連付けられた3つのタクソノミーを使うことになります。

  1. 公開された投稿のなかで、タクソノミー ‘category’ のタームが ‘list’ である投稿を抽出する
  2. そのなかでタクソノミー ‘post_tag’ のタームが ‘選択’ である投稿を抽出する
  3. それらの投稿に関連づけられているタクソノミー ‘asin’ のタームの一覧を取得する
SELECT DISTINCT t.name
FROM wp_posts AS p
INNER JOIN wp_term_relationships AS tr ON tr.object_id = p.ID
INNER JOIN wp_term_taxonomy AS tt ON tt.term_taxonomy_id = tr.term_taxonomy_id AND tt.taxonomy = 'asin'
INNER JOIN wp_terms AS t ON t.term_id = tt.term_id
WHERE p.ID IN (
  SELECT p2.ID
  FROM wp_posts AS p2
  INNER JOIN wp_term_relationships AS tr2 ON tr2.object_id = p2.ID
  INNER JOIN wp_term_taxonomy AS tt2 ON tt2.term_taxonomy_id = tr2.term_taxonomy_id AND tt2.taxonomy = 'post_tag'
  INNER JOIN wp_terms AS t2 ON t2.term_id = tt2.term_id AND t2.name = '選択'
  WHERE p2.ID IN (
    SELECT p3.ID
    FROM wp_posts AS p3
    INNER JOIN wp_term_relationships AS tr3 ON tr3.object_id = p3.ID
    INNER JOIN wp_term_taxonomy AS tt3 ON tt3.term_taxonomy_id = tr3.term_taxonomy_id AND tt3.taxonomy = 'category'
    INNER JOIN wp_terms AS t3 ON t3.term_id = tt3.term_id AND t3.name = 'list'
    WHERE p3.post_type = 'post' AND p3.post_status = 'publish'
  )
)
  • L13-18: 公開された(post_status が publish)投稿(post_type が post)のなかで、タクソノミー ‘category’ のタームが ‘list’ である投稿を抽出する
  • L7-12: L13-18 によって抽出された投稿の中で、カテゴリが list (category タクソノミーのタームが list)のものを抽出する
  • L1-L6: それらの投稿に関連づけられた本(asinタクソノミーのターム)を取得する。
  • L1: 1冊の本から複数のリストが作成され、それらが同じタグを有している場合もあるので DISTINCT を付して重複を除く

p、p2などと別名を付けなくてもSQL文としては通りましたが、EXPLAIN 文での分析結果がわかりづらくなるので別名を付けました。

上記を検証するための PHPコードは下記。

$q = new WP_Query( array(
    'post_type'      => 'post',
    'post_status'    => 'publish',
    'posts_per_page' => -1, // 全件
    'fields'         => 'ids', // IDのみ
    'tax_query'      => array(
        'relation' => 'AND',
        array(
            'taxonomy' => 'category',
            'field'    => 'slug',
            'terms'    => 'list',
        ),
        array(
            'taxonomy' => 'post_tag',
            'field'    => 'name',
            'terms'    => '選択',
        ),
    ),
) );

$asins = wp_get_object_terms( $q->posts, 'asin', $args );

Posted by

on

in category