Mysql
 sql >> Base de données >  >> RDS >> Mysql

Améliorer une requête en utilisant beaucoup de jointures internes à wp_postmeta, une table clé/valeur

Il semble que vous essayez d'obtenir un ensemble de résultats avec une ligne par article de type car . Il semble que vous souhaitiez afficher divers attributs de chaque voiture dans le message, et ceux-ci sont cachés dans postmeta .

Conseil de pro :Jamais utilisez SELECT * dans le logiciel à moins que vous ne sachiez absolument pourquoi vous le faites. Surtout avec des requêtes contenant beaucoup de JOIN opérations, SELECT * renvoie beaucoup de colonnes inutiles et redondantes.

Il y a une astuce de conception de requête à connaître pour le WordPress postmeta table. Si vous souhaitez obtenir un attribut particulier, procédez comme suit :

 SELECT p.ID, p.post_title,
        color.meta_value AS color
   FROM wp_posts AS p
   LEFT JOIN wp_postmeta AS color ON p.ID = color.post_id AND 'color' = color.meta_key
  WHERE p.post_status = 'publish'
    AND /* etc etc */

Il est très important de comprendre ce modèle lorsque vous faites ce que vous essayez de faire. Ce modèle est requis car postmeta est un type de tableau particulier appelé ou boutique. Que se passe t-il ici? Quelques éléments :

  1. En utilisant ce modèle, vous obtenez une ligne pour chaque message, avec quelques colonnes des posts table et un attribut particulier du postmeta tableau.
  2. Vous êtes LEFT JOIN le postmeta table afin que vous obteniez toujours une ligne si l'attribut est manquant.
  3. Vous utilisez un nom d'alias pour le postmeta table. Ici, c'est la postmeta AS color .
  4. Vous incluez le sélecteur pour meta_key (ici c'est 'color' = color.meta_key ) dans le ON condition de la jointure.
  5. Vous utilisez un alias dans votre SELECT clause pour présenter le postmeta.meta_value élément avec un nom de colonne approprié. Ici c'est color.meta_value AS color .

Une fois que vous vous êtes habitué à utiliser ce modèle, vous pouvez l'empiler, avec une cascade de LEFT JOIN opérations, pour obtenir de nombreux attributs différents, comme ceci.

     SELECT wp_posts.ID, wp_posts.post_title, wp_posts.whatever,
            color.meta_value        AS color,
            transmission.meta_value AS transmission,
            model.meta_value        AS model,
            brand.meta_value        AS brand
       FROM wp_posts

  LEFT JOIN wp_postmeta  AS color 
         ON wp_posts.ID = color.post_id        AND color.meta_key='color'

  LEFT JOIN wp_postmeta  AS transmission
         ON wp_posts.ID = transmission.post_id AND transmission.meta_key='transmission'

  LEFT JOIN wp_postmeta  AS model
         ON wp_posts.ID = model.post_id        AND model.meta_key='model'

  LEFT JOIN wp_postmeta  AS  brand
         ON wp_posts.ID = brand.post_id        AND brand.meta_key='brand'

      WHERE wp_posts.post_status = 'publish'
        AND wp_posts.post_type = 'car'
   ORDER BY wp_posts.post_title

J'ai fait un tas d'indentation sur cette requête pour faciliter la visualisation du modèle. Vous pouvez préférer un style d'indentation différent.

Il est difficile de savoir pourquoi vous aviez des problèmes de performances avec la requête dans votre question. C'est peut-être parce que vous obteniez une explosion combinatoire avec tous les INNER JOIN opérations qui ont ensuite été filtrées. Mais dans tous les cas, la requête que vous avez montrée ne renvoyait probablement aucune ligne.

Si vous rencontrez toujours des problèmes de performances, essayez de créer un index composé sur postmeta sur le (post_id, meta_key, meta_value) Colonnes. Si vous créez un plugin WordPress, c'est probablement un travail à faire au moment de l'installation du plugin.