代码之家  ›  专栏  ›  技术社区  ›  pigfox

Mysql空表联接失败

  •  -1
  • pigfox  · 技术社区  · 6 年前

    背景,我有一个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
    

    填充表keywords\u posts kp时,查询按预期工作。

    如果表keywords\u posts kp为空,则查询将永远不会返回任何内容。 我试图通过在WHERE子句中添加以下内容来解决此问题:

    AND kss.user_id IS NULL AND kss.post_id IS NULL
    

    期望的结果是:

    查询将返回除keywords\u posts kp表中列出的行以外的所有行。

    3 回复  |  直到 6 年前
        1
  •  1
  •   spencer7593    6 年前

    建议:

    WHERE 条款直至适当 ON 外部连接的条款。

    不要将老式的逗号语法(用于连接操作)与 JOIN 关键字语法。放弃逗号语法,只需使用 参加 。并将连接条件移动到 在…上 条款


    将条件移动到外部联接的ON子句将允许返回NULL值。

    如果我们使用WHERE子句,请注意条件

    WHERE ( col = some_non_null_val AND col IS NULL ) 
    

    保证永远不会计算为TRUE。(检查每一行的条件。)仅返回条件计算结果为TRUE的行。很可能你想用 OR 代替 AND

    但我们可以避免 如果我们重新定位条件

             col = some_non_null_val 
    

    在…上 外部连接的条款。


    我不愿意提供一个示例查询作为演示。原始查询生成一个半笛卡尔积;例如,在 users user_subscriptions 。。。匹配到的唯一标准 user\u订阅 keywords=1 .所以我不理解规格。

    用户 user\u订阅 应包括一些附加标准。

    如果没有更精确的规范,包括示例数据和预期输出的示例,我就无法提供SQL for OP用例示例。

        2
  •  0
  •   Jeffry Evan    6 年前

    我认为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
    
        3
  •  0
  •   pigfox    6 年前

    您好,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