Triple meta_key en una consulta SELECT personalizada

2

Estoy utilizando una consulta SELECT extraña para calcular el promedio de todas las calificaciones de publicaciones (almacenadas en wp_postmeta ) para un determinado usuario.

Mi consulta básicamente usa los siguientes argumentos:

  

post_author = 1 AND meta_key = 'rating' AND meta_value != 0 .

Esta consulta funciona perfectamente bien por sí misma, pero aquí es donde se complica. Necesito agregar algunas excepciones ...

  

meta_key = 'anonymous' AND meta_value != 'true'

Y otro ...

  

meta_key = 'original_author' AND meta_value = ''

Quiero recuperar solo los meta_valores rating , por lo que probablemente tendré más problemas al usar $wpdb->postmeta.meta_value .

Esto totaliza hasta un 3% de los argumentos meta_key y meta_value , con solo un meta_value que realmente quiero recuperar. Simplemente se vuelve más y más complicado ...

Ver mi código a continuación:

// Example value
    $user_id = 1;

// Calculate average post rating for user
    $ratings_query = $wpdb->get_results(
                        $wpdb->prepare("
                            SELECT $wpdb->postmeta.meta_value 
                            FROM $wpdb->postmeta
                                JOIN $wpdb->posts ON ($wpdb->postmeta.post_id = $wpdb->posts.id)
                                    WHERE ( 
                                        $wpdb->posts.post_author = %d AND 
                                        $wpdb->posts.post_type = 'post' AND 
                                        $wpdb->posts.post_status = 'publish' AND
                                        $wpdb->postmeta.meta_key = 'rating' AND 
                                        $wpdb->postmeta.meta_value != 0

                                        AND

                                        $wpdb->postmeta.meta_key = 'anonymous' AND 
                                        $wpdb->postmeta.meta_value != 'true'

                                        AND

                                        $wpdb->postmeta.meta_key = 'original_author' AND 
                                        $wpdb->postmeta.meta_value = '')
                        ", $user_id), ARRAY_N);

    if ( $ratings_query ) {
        $ratings_query = call_user_func_array('array_merge', $ratings_query);       
        $average_rating = round(array_sum($ratings_query) / count($ratings_query), 1);
    } else {
        $average_rating = 0;
    }
    
pregunta Swen 21.10.2016 - 00:34

2 respuestas

2

Su consulta es incorrecta. Para recuperar los valores de meta de triple meta_key, necesitará 3 combinaciones diferentes utilizando las meta de posts en la tabla de publicaciones. Compruebe el código a continuación:

// Example value
$user_id = 1;

// Calculate average post rating for user
$ratings_query = $wpdb->get_results(
                     $wpdb->prepare("
SELECT pmeta.meta_value  
    FROM wp_posts
      LEFT JOIN $wpdb->postmeta AS pmeta 
        ON (pmeta.post_id = $wpdb->posts.id) 
      LEFT JOIN $wpdb->postmeta AS pmeta1 
        ON (pmeta1.post_id = $wpdb->posts.id) 
      LEFT JOIN $wpdb->postmeta AS pmeta2 
        ON (pmeta2.post_id = $wpdb->posts.id) 
    WHERE $wpdb->posts.post_author = %d AND 
    $wpdb->posts.post_type = 'post' AND 
    $wpdb->posts.post_status = 'publish'
      AND (
        pmeta.meta_key = 'rating' 
        AND CAST(pmeta.meta_value AS CHAR) != '0'
      ) 
      AND (
        pmeta1.meta_key = 'anonymous' 
        AND CAST(pmeta1.meta_value AS CHAR) != 'true'
      ) 
      AND (
        pmeta2.meta_key = 'original_author' 
        AND CAST(pmeta2.meta_value AS CHAR) = ''
      )", $user_id), ARRAY_N);

Para recuperar los metadatos usando una consulta personalizada, necesitará 1 combinaciones para cada par de metadatos en la tabla de publicaciones, como se indicó anteriormente.

si imprime la última consulta SQL con el código echo $wpdb->last_query; , obtendrá una consulta SQL:

SELECT 
  pmeta.meta_value 
FROM
  wp_posts 
  LEFT JOIN wp_postmeta AS pmeta 
    ON (pmeta.post_id = wp_posts.id) 
  LEFT JOIN wp_postmeta AS pmeta1 
    ON (pmeta1.post_id = wp_posts.id) 
  LEFT JOIN wp_postmeta AS pmeta2 
    ON (pmeta2.post_id = wp_posts.id) 
WHERE wp_posts.post_author = 1 
  AND wp_posts.post_type = 'post' 
  AND wp_posts.post_status = 'publish' 
  AND (
    pmeta.meta_key = 'rating' 
    AND CAST(pmeta.meta_value AS CHAR) != '0'
  ) 
  AND (
    pmeta1.meta_key = 'anonymous' 
    AND CAST(pmeta1.meta_value AS CHAR) != 'true'
  ) 
  AND (
    pmeta2.meta_key = 'original_author' 
    AND CAST(pmeta2.meta_value AS CHAR) = ''
  )
    
respondido por el C Sabhar 23.10.2016 - 19:34
4

No hay nada malo con la otra respuesta, pero pensé que agregaría esto como un método diferente, ya que es simple y usa WP para resolver la consulta SQL. Sería un poco más pesado en recursos ya que hay consultas adicionales con la función get_post_meta .

$user_id = 1;
$args = array(
              'post_type' => 'post',
              'posts_per_page' => -1,
              'post_status' => 'publish',
              'orderby' => 'date',
              'order' => 'ASC',
              'meta_query' => array(
                                    'relation' => 'AND',
                                    array(
                                          'key' => 'post_author',
                                          'value' => $user_id
                                          ),
                                    array(
                                          'key' => 'rating',
                                          'compare' => '!=', // or'>'
                                          'value' => 0
                                          ),
                                    array(
                                          'key' => 'anonymous',
                                          'compare' => '!=',
                                          'value' => true
                                          ),
                                    array(
                                          'key' => 'original_author',
                                          'compare' => '!=',
                                          'value' => ''
                                          )
                                    )
              );

$RelevantPosts = get_posts($args);

$ratings = array();
foreach($RelevantPosts as $RelevantPost) {
    $ratings[] = get_post_meta($RelevantPost->ID, 'rating' , true);
}

if ( $RelevantPosts ) {
    $average_rating = round(array_sum($ratings) / count($ratings), 1);
} else {
    $average_rating = 0;
}

Sin embargo, es fácil de leer y entender, y siempre que no se ejecute en masa (por ejemplo, para todos sus usuarios a la vez) debería estar bien para los recursos.

    
respondido por el Bysander 26.10.2016 - 15:08

Lea otras preguntas en las etiquetas