背景,我有一个cron作业,它查询与帖子相关联的关键字,如果找到该关键字,就会向用户发送关于帖子的电子邮件。
cron作业每分钟运行一次,因此一旦用户收到电子邮件,通知就不会再次发生。运行以下查询:
SELECT DISTINCT p.id AS post_id, u.display_name, u.id AS user_id, u.email, k.keyword, k.id AS keyword_id
FROM posts p, user_subscriptions us, keywords_users ku, keywords k, users u
LEFT JOIN keyword_subscription_sent kss ON kss.user_id = u.id
LEFT JOIN keywords_posts kp ON kss.post_id = kp.post_id
WHERE us.keywords = 1
AND ku.user_id = u.id
AND ku.keyword_id = k.id
AND kp.keyword_id = k.id
# AND kss.user_id IS NULL AND kss.post_id IS NULL
LIMIT 0, 200
当填充表关键字kp时,查询按预期工作。
如果表keywords\u posts kp为空,查询将永远不会返回任何内容。我试图通过在where子句中添加以下内容来解决此问题:
AND kss.user_id IS NULL AND kss.post_id IS NULL
但是将此添加到where子句将导致查询在任何时候都不会返回任何内容。
期望的结果是:
查询将返回除keywords表中列出的行以外的所有行。
3条答案
按热度按时间smdnsysy1#
我认为kp\u keyword\u id=k.id根据where条件导致查询在kp为空的情况下不返回任何内容,请尝试将其放入join中,使其变成这样
von4xj4u2#
建议:
将要求列不为null的条件从
WHERE
条款直至适当的ON
外连接的子句。不要将老式的逗号语法(用于连接操作)与
JOIN
关键字语法。抛开逗号语法,只使用JOIN
. 并将连接条件移动到ON
条款。将条件移动到外部联接的on子句将允许返回null值。
如果我们使用where子句,请注意
保证永远不会评估为真(每个单独的行都会检查条件。)只会返回条件值为true的行。很可能你想用
OR
代替AND
.但我们可以避免
OR
如果我们重新定位条件到
ON
外连接的子句。我不愿意提供一个示例查询作为演示。原始查询产生一个半笛卡尔积;例如,在
users
以及user_subscriptions
... 匹配的唯一标准user_subscriptions
是keywords=1
. 所以我不明白说明书。op报告查询返回了正确的结果,但我怀疑查询实际上不符合预期的规范。我怀疑
users
以及user_subscriptions
应该包括一些额外的标准。如果没有更精确的规范,包括示例数据和预期输出的示例,我就不能凭良心提供sql for op用例示例。
2admgd593#
大家好,谢谢你们的意见。
以下措施奏效: