[ASP.NET Core] WordPressの公開ページをASP.NET Coreで作る
WordPressで独自のテーマを作っている時など、個別投稿ページでその記事に関連する投稿の一覧を表示したい場合がある。
その記事に指定されたタームがひとつだけなら同じタームを持つ記事を引っ張ってくるだけでいいかもしれない。 しかし例えばその記事にタームが3つも4つも設定されていたら、どういった基準で関連記事を取得するのが良いだろうか。
色々と試行錯誤した結果、共通するタームの数が多いものから順番に取得するという形に落ち着いた。
SELECT
p2.*
FROM
wp_posts p2
INNER JOIN (
SELECT
p.ID
FROM
wp_posts p
INNER JOIN wp_term_relationships tr
ON p.ID = tr.object_id
INNER JOIN wp_term_taxonomy tt
ON tr.term_taxonomy_id = tt.term_taxonomy_id
WHERE
tt.term_id IN(4, 13, 21) -- 対象の投稿に紐づいたタームID
AND p.post_type = 'post'
AND p.post_status = 'publish'
AND p.ID <> 1234 -- 対象の投稿を除外
GROUP BY
p.ID,
p.menu_order
ORDER BY
COUNT(p.ID) DESC,
p.menu_order
LIMIT 6
) p3
ON p2.ID = p3.ID
ORDER BY
p2.menu_order
ここではまずサブクエリで共通するタームIDを持つ投稿を一覧にし、タームの数が多い順に並べる。 そこから上位6件の投稿IDを切り出し、その投稿ID一覧を元に関連記事のデータを取得している。
最初は同じ考え方で以下のようなSQLを組み立ててみたが、これは失敗に終わった。
SELECT
p2.*
FROM
wp_posts p2
WHERE
p2.ID IN (
SELECT
p.ID
FROM
wp_posts p
INNER JOIN wp_term_relationships tr
ON p.ID = tr.object_id
INNER JOIN wp_term_taxonomy tt
ON tr.term_taxonomy_id = tt.term_taxonomy_id
WHERE
tt.term_id IN(4, 13, 21) -- 対象の投稿に紐づいたタームID
AND p.post_type = 'photo'
AND p.post_status = 'publish'
AND p.ID <> 1234 -- 対象の投稿を除外
GROUP BY
p.ID,
p.menu_order
ORDER BY
COUNT(p.ID) DESC,
p.menu_order
LIMIT 6
)
ORDER BY
p2.menu_order
SQL文としては成立しているように見えるが、これをMySQLで実行しようとすると以下のようなエラーが出てしまう。
要するに「このバージョンのMySQLではIN/ALL/ANY/SOMEの中のサブクエリでLIMITは使えませんよ」というエラーだ。 これはMySQLのドキュメントにも記載されていた。
しかし今回の場合は一度共通するタームの数で並べ替える必要があったのでどうしてもサブクエリが必要になった。 なのでやや見栄えは悪いが、最初に紹介したSQL文のようにサブクエリとテーブルをINNER JOINするという形に落ち着いた。