Mysql
 sql >> Database >  >> RDS >> Mysql

Unisciti a più tavoli, mantenendo NULL

Quando si utilizza un outer join, quindi si utilizza una delle colonne "outer" in un controllo di uguaglianza in WHERE clausola, converti il ​​tuo join esterno in un join interno. Questo perché la tua condizione che controlla la privacy del post richiede che il post sia presente:

AND p.privacy = 1 OR (p.privacy = 2 AND fr.fstatus = 1)

Quando un outer join sta per produrre una riga che corrisponde a una notifica senza un post, verificherebbe la condizione di cui sopra. Dal momento che il post non c'è, p.privacy restituirebbe NULL , "contaminando" entrambi i lati di OR , ed eventualmente fare in modo che l'intera condizione restituisca false .

Spostando questa condizione in ON la condizione del join risolverà il problema:

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

Un altro modo per risolvere questo problema sarebbe aggiungere un IS NULL condizione al tuo OR , in questo modo:

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