连接多个表,保留NULL

皮夫拉斯

我有4个表userpostsfollowsnotificationsposts表有一个名为的字段privacy,其中值1表示“任何人都可以看到”,值2表示“只有朋友可以看到”。

我的notifications桌子看起来像这样:

id user_id tonotify_id notification post_id
1  2       3           ---          1
2  3       2           ---          2
3  2       4           ---          3

我的follows桌子看起来像这样:

id user_id tofollow_id status fstatus
1  1       2           1      1
2  1       3           1      1

字段fstatus值1表示他们也是朋友。

现在,我尝试获取由某个特定用户关注的人发出的所有通知(比如说ID为1的用户)。假设1跟随用户2和3,我需要从上表中获取所有通知。但是,在此之前,我需要确保该帖子(由用户在此tonotify_id列中发布)可用。也就是说,我需要检查隐私设置。我有以下代码:

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 = 1 OR (p.privacy = 2 AND fr.fstatus = 1)
ORDER BY n.id DESC

除一个小故障外,它似乎正在工作。由于用户1没有跟随用户4,因此所有针对4的通知都不会出现,即使帖子是公开的也不会出现。我的猜测与之有关JOIN follows fr ON (n.tonotify_id = fr.tofollow_id),因为由于用户1并未关注4,所以没有匹配该联接的行。对解决这个有什么建议吗?

谢尔盖·卡里尼琴科(Sergey Kalinichenko)

我确实尝试过[外部联接],但是输出是相同的。

当您使用外部联接,然后在WHERE子句中的相等性检查中使用“外部”列之一时,会将外部联接转换为内部联接。这是因为您检查帖子私密性的条件要求帖子在那儿:

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

当外部联接将要产生与没有帖子的通知相对应的行时,它将检查上述条件。由于该职位不在那儿,因此p.privacy将评估为NULL,“污染”该建筑的两侧OR,最终使整个状况评估为false

将此条件移到联接条件ON中将解决此问题:

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

解决此问题的另一种方法是在IS NULL条件中添加一个条件OR,如下所示:

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章