Cómo seleccionar publicaciones con etiquetas/categorías específicas en WordPress
Pregunta
Esta es una pregunta muy específica sobre mysql tal como se implementó en WordPress.
Estoy intentando desarrollar un complemento que muestre (seleccione) publicaciones que tengan ' específicosetiquetas' y pertenecen a ' específicocategorias' (ambos múltiples)
Me dijeron que es imposible debido a la forma en que se almacenan las categorías y etiquetas:
wp_posts
contiene una lista de publicaciones, cada publicación tiene una "ID"wp_terms
contiene una lista de términos (tanto categorías como etiquetas).Cada término tiene un TERM_IDwp_term_taxonomy
tiene una lista de términos con sus TERM_ID y tiene una definición de Taxonomía para cada uno de ellos (ya sea una Categoría o una Etiqueta)wp_term_relationships
tiene asociaciones entre términos y publicaciones
¿Cómo puedo unirme a las mesas para obtener todas las publicaciones con etiquetas "Nuclear"? y ¿"Ofertas" que también pertenecen a la categoría "Categoría1"?
Solución
Te malentendí.Pensé que querías Nuclear o Ofertas.Lo siguiente debería proporcionarle solo Nuclear y Ofertas.
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')
Otros consejos
Qué estructura de base de datos más asquerosa.
De todos modos, haría algo como esto (tenga en cuenta que prefiero EXISTS a las uniones, pero puede reescribirlas como uniones si lo desea;la mayoría de los analizadores de consultas los colapsarán en el mismo plan de consultas de todos modos).Es posible que tengas que hacer algunos malabarismos adicionales de una forma u otra 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"
)
)
)
Entonces probé ambas opciones en mi base de datos de WordPress.Busqué la categoría "Tecnología" en mis publicaciones con las etiquetas "Perl" Y "Programación".
eric Funcionó una vez que agregué una coma faltante en la declaración de selección inicial.Devolvió 3 registros.El problema es que la sección que busca "post_tag" en realidad funciona como una opción OR.Una de mis publicaciones solo tenía una etiqueta, no ambas.También sería bueno hacer SELECT DISTINCT.
Lo intenté matt versión, pero seguía devolviendo un conjunto vacío.Puedo intentar "hacer malabarismos" con ello.
Prueba esto:
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'))
Básicamente, estoy empleando 2 copias de las tablas secundarias pertinentes: términos, term_taxonomy y term_relationship.Una copia aplica la restricción 'Categoría 1', la otra la restricción 'Nuclear' o 'Acuerdos'.
Por cierto, ¿qué tipo de proyecto es este con publicaciones sobre acuerdos nucleares?¿Estás intentando incluirnos en alguna lista del gobierno?;)
Gracias @Eric, ¡funciona!Sólo algunas correcciones de código para referencia futura:
- las primeras declaraciones seleccionadas pierden un coma después de wp_term_relationship tr2
- En la misma declaración de selección se debe cambiar lo siguiente:
wp_terms t2, wp_term_taxonomy tt2, wp_term_relationship
tr2
debiera ser
wp_terms t3, wp_term_taxonomy tt3, wp_term_relationship
tr3
Realmente tan buena respuesta..me ayudo mucho..
Genial porque me dio un enfoque básico para construir mi consulta compleja.
una pequeña corrección, para usuarios listos como yo :)
"wp_term_relationship" dará 'no existe error' ..usar wp_term_relaciones ya que es el nombre correcto de la tabla.
gracias eric