web-dev-qa-db-fra.com

Triple meta_key sur une requête SELECT personnalisée

J'utilise une requête SELECT étrange pour calculer la moyenne de toutes les notes de publication (stockées dans wp_postmeta) pour un utilisateur donné.

Ma requête utilise essentiellement les arguments suivants:

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

Cette requête fonctionne parfaitement bien d'elle-même, mais voici où cela se complique. J'ai besoin d'ajouter quelques exceptions ...

meta_key = 'anonymous' ET meta_value != 'true'

Et un autre...

meta_key = 'original_author' ET meta_value = ''

Je souhaite récupérer uniquement les valeurs méta_valeurs rating, de sorte que je rencontrerai probablement davantage de problèmes avec $wpdb->postmeta.meta_value.

Cela totalise jusqu'à 3 arguments meta_key et meta_value, avec un seul meta_value que je souhaite récupérer. Cela devient de plus en plus délicat ...

Voir mon code ci-dessous:

// 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;
    }
2
Swen

Votre requête est incorrecte. Pour récupérer des méta-valeurs pour triple meta_key, vous aurez besoin de 3 jointures différentes à l'aide de la table posts meta on posts. Vérifiez le code ci-dessous:

// 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);

Pour récupérer des métadonnées à l'aide d'une requête personnalisée, vous aurez besoin d'une jointure pour chaque paire de métadonnées sur la table des publications, comme ci-dessus.

si vous imprimez la dernière requête SQL en utilisant le code echo $wpdb->last_query;, vous obtiendrez la requête 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) = ''
  )
2
C Sabhar

Il n’ya rien de mal à l’autre réponse, mais j’ai pensé que j’ajouterais cette méthode de manière différente, car c’est simple et elle utilise WP pour élaborer la requête SQL. Ce serait un peu plus lourd en ressources car il y a des requêtes supplémentaires avec la fonction 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;
}

Il est cependant simple à lire et à comprendre et tant que cela ne fonctionne pas en masse (par exemple pour tous vos utilisateurs à la fois), cela devrait convenir pour les ressources.

4
Bysander