后台,我有一个cron作业,用于查询与帖子相关的关键字,如果找到该关键字,则会通过电子邮件向用户发送帖子。
cron作业每分钟运行一次,因此一旦用户通过电子邮件发送通知,就不应该再次发生通知。 运行以下查询:
Hotspot safepoints
当填充表keywords_posts kp时,查询按预期工作。
如果表keywords_posts kp为空,则查询将永远不会返回任何内容。 我试图通过添加到WHERE子句来解决这个问题:
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
但是将此添加到WHERE子句将导致查询在任何时候都不会返回任何内容。
期望的结果是:
查询将返回除keywords_posts kp表中列出的所有行。
答案 0 :(得分:1)
建议:
将需要列为非NULL的条件从WHERE
子句重新定位到外连接的相应ON
子句。
不要将旧式逗号语法(用于连接操作)与JOIN
关键字语法混合使用。抛弃逗号语法并使用JOIN
。并将连接条件移动到ON
子句。
将条件移动到外部联接的ON子句将允许返回NULL值。
如果我们这样做WHERE子句,请注意条件
WHERE ( col = some_non_null_val AND col IS NULL )
保证永远不会评估为TRUE。 (检查每个单独行的条件。)仅返回条件评估为TRUE的行。可能你打算用OR
代替AND
。
但如果我们只是重新定位条件
,我们可以避免OR
col = some_non_null_val
到外连接的ON
子句。
我犹豫是否提供示例查询作为演示。最初的查询是生产半笛卡尔积;例如,似乎是users
和user_subscriptions
之间的交叉联接...与user_subscriptions
匹配的唯一条件是keywords=1
。所以我不理解规范。
OP报告查询返回了正确的结果,但我怀疑查询实际上是否满足预期的规范。我怀疑users
和user_subscriptions
之间的匹配应该包含一些额外的标准。
如果没有更精确的规范,包括样本数据和预期输出的示例,我不能在良心上为OP用例提供示例SQL。
答案 1 :(得分:0)
我认为你的WHERE条件中的kp_keyword_id = k.id导致查询在kp为空的情况下不返回任何内容,请尝试将其放入JOIN中,使其变为这样
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 AND kp.keyword_id = k.id
WHERE us.keywords = 1
AND ku.user_id = u.id
AND ku.keyword_id = k.id
LIMIT 0, 200
答案 2 :(得分:0)
你好vveryone,谢谢你输入。
以下工作:
SELECT * FROM (SELECT u.id as user_id, u.email, u.display_name, k.id as keyword_id, k.keyword, p.id AS post_id, kp.post_id AS kp_post_id, kp.keyword_id AS kp_keyword_id,
ku.user_id AS ku_user_id, ku.keyword_id AS ku_keyword_id
FROM users u, keywords k, posts p, keywords_posts kp, user_subscriptions us, keywords_users ku
WHERE kp.post_id = p.id AND us.keywords = 1 AND kp.keyword_id = k.id AND ku.keyword_id = k.id AND u.id = ku.user_id
GROUP BY kp.post_id, u.id) AS ukp LEFT JOIN keyword_subscription_sent kss ON ukp.user_id = kss.user_id AND kss.post_id = ukp.post_id WHERE kss.post_id IS NULL