たとえば「選択」でタグづけされた公開「リスト」投稿で引用されている「本」を一覧したいとします。これは投稿に関連付けられた3つのタクソノミーを使うことになります。
- 公開された投稿のなかで、タクソノミー ‘category’ のタームが ‘list’ である投稿を抽出する
- そのなかでタクソノミー ‘post_tag’ のタームが ‘選択’ である投稿を抽出する
- それらの投稿に関連づけられているタクソノミー ‘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 );