Gdy używasz sprzężenia zewnętrznego, a następnie użyj jednej z kolumn „zewnętrznych” podczas sprawdzania równości w WHERE
klauzula, konwertujesz sprzężenie zewnętrzne na sprzężenie wewnętrzne. Dzieje się tak, ponieważ warunek sprawdzający prywatność posta wymaga, aby post tam był:
AND p.privacy = 1 OR (p.privacy = 2 AND fr.fstatus = 1)
Kiedy zewnętrzne złączenie ma wytworzyć wiersz, który odpowiada powiadomieniu bez wpisu, sprawdzi powyższy warunek. Ponieważ posta tam nie ma, p.privacy
oceniłby na NULL
, "zanieczyszczając" obie strony OR
, a ostatecznie sprawić, że cały warunek zostanie oceniony jako false
.
Przenoszenie tego warunku do ON
warunek przyłączenia rozwiąże problem:
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
Innym sposobem, aby to naprawić, byłoby dodanie IS NULL
warunek do Twojego OR
, tak:
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