Maison >base de données >tutoriel mysql >Pourquoi mon PostgreSQL LEFT JOIN ne renvoie-t-il pas les lignes avec un nombre de 0 ?

Pourquoi mon PostgreSQL LEFT JOIN ne renvoie-t-il pas les lignes avec un nombre de 0 ?

DDD
DDDoriginal
2025-01-14 11:12:10493parcourir

Why Doesn't My PostgreSQL LEFT JOIN Return Rows with a Count of 0?

PostgreSQL LEFT JOIN et nombres zéro manquants

Le LEFT JOIN de PostgreSQL est conçu pour renvoyer toutes les lignes de la table de gauche, même s'il n'y a aucune correspondance dans la table de droite. Cependant, des conditions de clause WHERE mal placées peuvent effectivement transformer un LEFT JOIN en un INNER JOIN, en omettant les lignes avec un nombre nul.

Ce problème survient souvent lorsque les conditions de filtrage basées sur la bonne table sont placées dans la clause WHERE. Prenons cet exemple :

<code class="language-sql">SELECT o.name AS organisation_name,
       COALESCE(COUNT(exam_items.id)) AS total_used
FROM   organisations o
LEFT   JOIN exam_items e ON o.id = e.organisation_id
WHERE  e.item_template_id = #{sanitize(item_template_id)}
AND    e.used = true
GROUP  BY o.name
ORDER  BY o.name</code>

La clause WHERE filtre exam_items pour des item_template_id et used = true spécifiques. Ceci filtre après la jointure, en supprimant les lignes de organisations qui n'ont pas de lignes correspondantes dans exam_items satisfaisant ces conditions.

La solution : déplacer le filtrage vers la condition JOIN

Pour conserver toutes les lignes de organisations, même celles sans lignes correspondantes dans exam_items, déplacez les conditions de filtrage de la clause WHERE vers la clause JOIN :

<code class="language-sql">SELECT o.name AS organisation_name,
       COUNT(e.id) AS total_used
FROM   organisations o
LEFT   JOIN exam_items e
       ON e.organisation_id = o.id
       AND e.item_template_id = #{sanitize(item_template_id)}
       AND e.used = true
GROUP  BY o.name
ORDER  BY o.name</code>

Maintenant, le filtrage se produit pendant la jointure. Seules les lignes exam_items répondant aux critères sont prises en compte pour la jointure. organisations les lignes sans lignes correspondantes seront toujours incluses, ce qui donnera des total_used valeurs de 0.

Optimisation supplémentaire : COUNT() et COALESCE

La requête d'origine utilise COALESCE(COUNT(exam_items.id)). C'est redondant. COUNT() ne revient jamais NULL ; il renvoie 0 si aucune ligne ne correspond. Par conséquent, COALESCE n'est pas nécessaire et peut être supprimé pour améliorer l'efficacité des requêtes.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn