mysql空表联接失败

r6l8ljro  于 2021-06-21  发布在  Mysql
关注(0)|答案(3)|浏览(253)

背景,我有一个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表中列出的行以外的所有行。

smdnsysy

smdnsysy1#

我认为kp\u keyword\u id=k.id根据where条件导致查询在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
von4xj4u

von4xj4u2#

建议:
将要求列不为null的条件从 WHERE 条款直至适当的 ON 外连接的子句。
不要将老式的逗号语法(用于连接操作)与 JOIN 关键字语法。抛开逗号语法,只使用 JOIN . 并将连接条件移动到 ON 条款。
将条件移动到外部联接的on子句将允许返回null值。
如果我们使用where子句,请注意

WHERE ( col = some_non_null_val AND col IS NULL )

保证永远不会评估为真(每个单独的行都会检查条件。)只会返回条件值为true的行。很可能你想用 OR 代替 AND .
但我们可以避免 OR 如果我们重新定位条件

col = some_non_null_val

ON 外连接的子句。
我不愿意提供一个示例查询作为演示。原始查询产生一个半笛卡尔积;例如,在 users 以及 user_subscriptions ... 匹配的唯一标准 user_subscriptionskeywords=1 . 所以我不明白说明书。
op报告查询返回了正确的结果,但我怀疑查询实际上不符合预期的规范。我怀疑 users 以及 user_subscriptions 应该包括一些额外的标准。
如果没有更精确的规范,包括示例数据和预期输出的示例,我就不能凭良心提供sql for op用例示例。

2admgd59

2admgd593#

大家好,谢谢你们的意见。
以下措施奏效:

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

相关问题