Como selecionar postagens com tags/categorias específicas no WordPress
Pergunta
Esta é uma questão muito específica em relação MySQL conforme implementado em WordPress.
Estou tentando desenvolver um plugin que mostre (selecione) postagens que possuem 'Tag'e pertencem a 'específicos'categorias' (ambos múltiplos)
Disseram-me que é impossível porque a forma como as categorias e tags são armazenadas:
wp_posts
contém uma lista de postagens, cada postagem tem um "ID"wp_terms
contém uma lista de termos (categorias e tags).Cada termo tem um TERM_IDwp_term_taxonomy
possui uma lista de termos com seus TERM_IDs e possui uma definição de taxonomia para cada um deles (uma categoria ou uma tag)wp_term_relationships
tem associações entre termos e postagens
Como posso juntar as tabelas para obter todos os posts com tags "Nuclear" e "Ofertas" que também pertencem à categoria "Categoria1"?
Solução
Eu te entendi mal.Achei que você queria Nuclear ou Deals.O texto abaixo deve fornecer apenas Nuclear e negócios.
select p.*
from wp_posts p, wp_terms t, wp_term_taxonomy tt, wp_term_relationship tr,
wp_terms t2, wp_term_taxonomy tt2, wp_term_relationship tr2
wp_terms t2, wp_term_taxonomy tt2, wp_term_relationship tr2
where p.id = tr.object_id and t.term_id = tt.term_id and tr.term_taxonomy_id = tt.term_taxonomy_id
and p.id = tr2.object_id and t2.term_id = tt2.term_id and tr2.term_taxonomy_id = tt2.term_taxonomy_id
and p.id = tr3.object_id and t3.term_id = tt3.term_id and tr3.term_taxonomy_id = tt3.term_taxonomy_id
and (tt.taxonomy = 'category' and tt.term_id = t.term_id and t.name = 'Category1')
and (tt2.taxonomy = 'post_tag' and tt2.term_id = t2.term_id and t2.name = 'Nuclear')
and (tt3.taxonomy = 'post_tag' and tt3.term_id = t3.term_id and t3.name = 'Deals')
Outras dicas
Que estrutura bruta de banco de dados.
De qualquer forma, eu faria algo assim (observe que prefiro EXISTS a junções, mas você pode reescrevê-las como junções, se desejar;a maioria dos analisadores de consulta irá recolhê-los para o mesmo plano de consulta de qualquer maneira).Você pode ter que fazer alguns malabarismos adicionais de uma forma ou de outra para que funcione ...
SELECT *
FROM wp_posts p
WHERE EXISTS( SELECT *
FROM wp_term_relationship tr
WHERE tr.object_id = p.id
AND EXISTS( SELECT *
FROM wp_term_taxonomy tt
WHERE tt.term_taxonomy_id = tr.term_taxonomy_id
AND tt.taxonomy = 'category'
AND EXISTS( SELECT *
FROM wp_terms t
WHERE t.term_id = tt.term_id
AND t.name = "Category1"
)
)
AND EXISTS( SELECT *
FROM wp_term_taxonomy tt
WHERE tt.term_taxonomy_id = tr.term_taxonomy_id
AND tt.taxonomy = 'post_tag'
AND EXISTS( SELECT *
FROM wp_terms t
WHERE t.term_id = tt.term_id
AND t.name = "Nuclear"
)
AND EXISTS( SELECT *
FROM wp_terms t
WHERE t.term_id = tt.term_id
AND t.name = "Deals"
)
)
)
Então tentei as duas opções no meu banco de dados WordPress.Procurei a categoria "Tech" em meus posts com as tags "Perl" AND "Programming".
Érico funcionou depois que adicionei uma vírgula ausente na instrução select inicial.Ele retornou 3 registros.O problema é que a seção que procura o "post_tag" está na verdade funcionando como uma opção OR.Uma das minhas postagens tinha apenas uma tag, não ambas.Também seria bom fazer o SELECT DISTINCT.
tentei Matt versão, mas continuou retornando um conjunto vazio.Posso tentar "fazer malabarismos" com isso.
Experimente isto:
select p.*
from wp_posts p,
wp_terms t, wp_term_taxonomy tt, wp_term_relationship tr
wp_terms t2, wp_term_taxonomy tt2, wp_term_relationship tr2
where p.id = tr.object_id
and t.term_id = tt.term_id
and tr.term_taxonomy_id = tt.term_taxonomy_id
and p.id = tr2.object_id
and t2.term_id = tt2.term_id
and tr2.term_taxonomy_id = tt2.term_taxonomy_id
and (tt.taxonomy = 'category' and tt.term_id = t.term_id and t.name = 'Category1')
and (tt2.taxonomy = 'post_tag' and tt2.term_id = t2.term_id and t2.name in ('Nuclear', 'Deals'))
Essencialmente, estou empregando 2 cópias das tabelas filho pertinentes - termos, term_taxonomia e term_relationship.Uma cópia aplica a restrição 'Categoria1', a outra a restrição 'Nuclear' ou 'Negócios'.
Aliás, que tipo de projeto é esse com postagens sobre acordos nucleares?Você está tentando nos incluir em alguma lista do governo?;)
Obrigado @Eric, funciona!Apenas algumas correções de código para referência futura:
- as primeiras instruções selecionadas perdem o coma após wp_term_relationship tr2
- Na mesma instrução select, o seguinte deve ser alterado:
wp_terms t2, wp_term_taxonomy tt2, wp_term_relationship
tr2
deveria estar
wp_terms t3, wp_term_taxonomy tt3, wp_term_relationship
tr3
Realmente uma ótima resposta ..me ajudou muito..
ótimo bcoz., me deu uma abordagem básica para construir minha consulta complexa!
uma pequena correção, para usuários prontos como eu :)
"wp_term_relationship" dará "erro não existe" ..usar wp_term_relationships pois é o nome correto da tabela.
Obrigado Érico