Lorsque vous utilisez une jointure externe, puis utilisez l'une des colonnes "externes" dans une vérification d'égalité dans WHERE
clause, vous convertissez votre jointure externe en jointure interne. C'est parce que votre condition qui vérifie la confidentialité de la publication exige que la publication soit là :
AND p.privacy = 1 OR (p.privacy = 2 AND fr.fstatus = 1)
Lorsqu'une jointure externe est sur le point de produire une ligne correspondant à une notification sans publication, elle vérifie la condition ci-dessus. Puisque le message n'est pas là, p.privacy
serait évalué à NULL
, "contaminant" les deux côtés du OR
, et finalement faire en sorte que toute la condition soit évaluée à false
.
Déplacer cette condition dans le ON
condition de la jointure résoudra le problème :
SELECT
u.username AS sender,
ux.username AS receiver,
p.id
FROM notifications n
JOIN follows f ON (n.user_id = f.tofollow_id)
JOIN follows fr ON (n.tonotify_id = fr.tofollow_id)
JOIN user u ON (u.id = n.user_id)
JOIN user ux ON (ux.id = n.tonotify_id)
LEFT JOIN posts p ON (n.posts_id = p.id)
AND (p.privacy = 1 OR (p.privacy = 2 AND fr.fstatus = 1))
WHERE f.user_id = 1
AND fr.user_id = 1
AND f.status = 1
ORDER BY n.id DESC
Une autre façon de résoudre ce problème serait d'ajouter un IS NULL
condition à votre OR
, comme ceci :
SELECT
u.username AS sender,
ux.username AS receiver,
p.id
FROM notifications n
JOIN follows f ON (n.user_id = f.tofollow_id)
JOIN follows fr ON (n.tonotify_id = fr.tofollow_id)
JOIN user u ON (u.id = n.user_id)
JOIN user ux ON (ux.id = n.tonotify_id)
LEFT JOIN posts p ON (n.posts_id = p.id)
WHERE f.user_id = 1
AND fr.user_id = 1
AND f.status = 1
AND (p.privacy IS NULL OR p.privacy = 1 OR (p.privacy = 2 AND fr.fstatus = 1))
ORDER BY n.id DESC