Obtener publicación con múltiples meta keys y valores
Estoy tratando de obtener una publicación basada en las siguientes meta keys.
post_code
con432C
location
conXYZ
Ambos pertenecen a un CPT. Estoy tratando de obtener la Publicación con ambos meta_values.
No quiero una relación OR, quiero una relación AND. He probado varios objetos WP_Query
y todavía no he encontrado una solución después de horas de búsqueda.

Esto debería funcionar. La relación por defecto es AND (Y) así que no será necesario especificarla.
$args = array(
'post_type' => 'wpse_cpt',
'meta_query' => array(
array(
'key' => 'post_code',
'value' => '432C',
),
array(
'key' => 'location',
'value' => 'XYZ',
),
),
);
$query = new WP_Query( $args );

Lo he intentado, pero esto me da demasiada información. Estoy tratando de obtener resultados usando $wpdb... ¿Es posible?

Esto devolverá los resultados que describiste en tu pregunta. Así que, o necesitas hacer una consulta más específica, o asegurarte de que tus posts tengan metadatos precisos.

$args = array(
'post_type' => 'wpse_cpt',
'meta_query' => array(
'relation' => 'AND' //**** Usa AND u OR según tu cláusula Where requerida
array(
'key' => 'post_code',
'value' => '432C',
),
array(
'key' => 'location',
'value' => 'XYZ',
),
),
);
$query = new WP_Query( $args );

Editar de nuevo: Ah, no respondí a la pregunta. Seleccionarías a.*
para obtener todas las columnas de los posts con los valores de clave coincidentes, en lugar de seleccionar c.meta_value
.
La siguiente consulta SQL/$wpdb
seleccionará todos los meta_value%s
de un post con post_type de $postType
y un valor meta_key de $metaKey
. Por lo tanto, selecciona todos los valores diferentes de una meta_key dada (a través de '$metaKey'). La tabla term_relationships
es la tabla auxiliar de WordPress para conexiones de relaciones entre tablas. wp_posts
es la tabla 'posts' de WordPress, y wp_postmeta
es la tabla 'postmeta' de WordPress. (Nota: Si estás usando tablas personalizadas, estos nombres de tabla serían diferentes).
~ Editado para agregar notas de 'haciendo', solicitado por @MikeNGarrett
/* $wpdb es una variable global proporcionada por el 'motor' de WordPress
** para consultar tablas de la base de datos de WordPress.
*/
global $wpdb;
$postType = 'mycustomposttype';
$metaKey = 'mymetakey';
$query = "
SELECT c.meta_value
FROM wp_posts a
LEFT JOIN wp_term_relationships b
ON (a.ID = b.object_id)
LEFT JOIN wp_postmeta c
ON (a.ID = c.post_id)
WHERE a.post_type = %s AND c.meta_key = %s";
$metaValues = $wpdb->prepare(query, [$postType, $metaKey]);
$metaValues = $wpdb->get_results($metaValues);
Notas: Solo estoy reutilizando la variable $metaValues. No hay otra razón para escribir los resultados de $metaValues prepare()
de nuevo en la variable $metaValues. Sin embargo, debes pasar $metaValues a get_results()
.

¡Hola Eric! ¿Puedes proporcionar un poco más de contexto? Especialmente respondiendo "¿Qué hace este código?" y "¿Por qué es la mejor manera de lograr esto?"

@MikeNGarrett, he añadido notas. En realidad, puedes devolver los valores que quieras de cualquiera de esas tres tablas con la consulta. Solo necesitas cambiar de qué tabla estás preguntando/comparando. Mediante a
, b
, c
y .
y el nombre de la columna.

@MikeGarrett, "¿Por qué es la mejor manera de lograr esto?". Honestamente, no sé si esta es la 'mejor' manera de lograrlo. Sin embargo, funciona. También me interesaría si alguien encuentra una forma mejor/más rápida. Creo que esta es la forma menos exigente de hacerlo, según mis habilidades y conocimientos actuales en este momento.

SOLUCIÓN
La solución aceptada a continuación funcionó, sin embargo, quería saber ¿cómo está funcionando?
Así es como funciona:
SELECT * FROM wp_posts p, wp_postmeta m1, wp_postmeta m2
WHERE p.ID = m1.post_id AND p.ID = m2.post_id
AND m1.meta_key = 'key1' AND m1.meta_value = 'value1'
AND m2.meta_key = 'key2' AND m2.meta_value = 'value2'
AND p.post_type = 'cpt' AND p.post_status = 'published'

Probé la solución con WP_Query sugerida anteriormente, pero obtuve un resultado vacío. La sugerida por Sheraz Ahmed funciona bien. Aquí está mi propia versión por si sirve de algo:
//base de datos
wp_posts
+---------+--------------------+--------------+
| ID | post_title | post_type |
+---------+--------------------+--------------+
| 8567 | Introducción a MySQL| talk |
+---------+--------------------+--------------+
| 8590 | Introducción a PHP | talk |
+---------+--------------------+--------------+
wp_postmeta
+---------------+------------+----------------+
| post_id | meta_key | meta_value |
+---------------+------------+----------------+
| 8567 | speaker | John Doe |
+---------------+------------+----------------+
| 8567 | year_of | 2021 |
+---------------+------------+----------------+
| 8590 | speaker | John Doe |
+---------------+------------+----------------+
| 8590 | year_of | 2021 |
+---------------+------------+----------------+
//buscar por speaker y año
$speaker = "John Doe";
$year_of = "2021";
$talks = $wpdb->get_results(
$wpdb->prepare(
'SELECT post_title, meta_value AS speaker
FROM '.$wpdb->prefix.'posts AS pt, '.$wpdb->prefix.'postmeta AS pm
WHERE post_type = %s AND pm.post_id = pt.id AND ( meta_key = %s AND meta_value = %s )
AND post_id IN ( SELECT post_id FROM nm_postmeta WHERE meta_key = %s AND meta_value = %s )',
array( 'talk',
'speaker',
$speaker,
'year_of',
$year_of )
)
);
foreach ( $talks as $talk ) {
echo "<p>".$talk->speaker.': '.$talk_homily->post_title."</p>";
}
John Doe: Introducción a MySQL
John Doe: Introducción a PHP

Sería genial si pudieras explicar el código y cómo resuelve el problema.

Ya lo he explicado, por favor prueba estos parámetros usando estos parámetros, automáticamente resolverá el problema
