sql >> Base de Datos >  >> RDS >> Mysql

Unir varias tablas, manteniendo NULL

Cuando usa una combinación externa y luego usa una de las columnas "externas" en una verificación de igualdad en WHERE cláusula, convierte su combinación externa en una combinación interna. Esto se debe a que su condición que verifica la privacidad de la publicación requiere que la publicación esté allí:

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

Cuando una combinación externa está a punto de producir una fila que corresponde a una notificación sin publicación, verificaría la condición anterior. Dado que la publicación no está allí, p.privacy evaluaría a NULL , "contaminando" ambos lados del OR , y finalmente hacer que toda la condición se evalúe como false .

Mover esta condición a ON la condición de la unión solucionará el 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

Otra forma de solucionar esto sería agregar un IS NULL condición a su OR , así:

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