【问题标题】:SQL statement for join but not in other table用于连接但不在其他表中的 SQL 语句
【发布时间】:2013-07-17 10:20:05
【问题描述】:

我有两张桌子:customermailing

+==========+  +=============+
| customer |  | mailing     |
+==========+  +=============+
| id       |  | id          |
+----------+  +-------------+
| name     |  | customer_id |
+----------+  +-------------+
              | mailing_id  |
              +-------------+

每次我向客户发送邮件时,我都会在邮件表中使用该邮件 ID 添加一行。一封邮件可以发送给多个客户。

我想要一个 sql 调用来返回所有尚未收到特定邮件的客户。怎么做?

我正在使用 mysql

【问题讨论】:

    标签: mysql sql select


    【解决方案1】:
    select * from customer where id not in (
        select customer_id from mailing where mailing_id = @mailing_id
    )
    

    【讨论】:

    • 如果是 MySQL,IN () 在包含子查询时无法正常工作,即使在非常小的表上也可以运行数小时
    • @DanFromGermany 真的吗?根据此链接,它与 NOT EXISTS explainextended.com/2009/09/18/… 相当
    • 为什么子查询中有条件?不需要吧?
    • @joe776 该帖子来自 2009 年,与此问题进行比较:stackoverflow.com/questions/6135376/… "永远不要将 IN 与子查询一起使用;这是出了名的慢。只能将 IN 与固定的值列表一起使用."
    • @DanFromGermany 恕我直言,评估查询计划胜过“我从不使用 X,因为它非常慢”。答案中没有证据表明为什么会这样。当然,它始终取决于数据库、索引等内部的实际数据......
    【解决方案2】:

    类似

    Select c.ID, c.Name
    From Customers C
    left Join mailing m On c.id = m.customer_id
    where m.customer_id is null
    

    【讨论】:

    • 而且这个是最快的,除非你必须使用 distinct!
    【解决方案3】:
    SELECT * FROM customers c
    JOIN mailings m
    ON c.id = m.id
    WHERE NOT EXISTS (
        SELECT id
        FROM mailings i
        WHERE i.id = c.id
        GROUP BY i.id
    )
    

    【讨论】:

    • 我现在不确定这是否 100% 正确,如果 OP 需要任何进一步的帮助,请设置一个 sqlfiddle
    • customermailing 之间的连接要求已经有客户的邮件。此外,如果有客户的邮件,子查询总是返回一个结果,所以如果有任何邮件,你将不会得到结果。
    • 对,已更新 :) 我仍然不确定IN ()IN () 中的子查询有很多问题,我经常读到它们不起作用,即使使用percona 或 Mariadb
    【解决方案4】:

    您所描述的称为ANTI JOIN。在 SQL 中通常有三种不同的方式来表述它:带有子查询的 NOT IN 条件、带有相关子查询的 NOT EXISTS 条件或带有 NOT NULL 条件的 LEFT JOIN。 因此,对于您的查询,可能性是:

    SELECT *
    FROM customer
    WHERE id NOT IN
        ( SELECT customer_id
         FROM mailing)
    SELECT *
    FROM customer c
    WHERE NOT EXISTS
        ( SELECT customer_id
         FROM mailing m
         WHERE m.customer_id = c.id)
    SELECT *
    FROM customer c
    LEFT JOIN mailing m ON c.id = m.customer_id
    WHERE m.customer_id IS NULL

    This blog post 将不同的可能性与 MySQL 5.1 进行比较。据此,LEFT JOIN / IS NULLNOT INNOT EXISTS 快。
    但是,您应该自己尝试哪一个是最快的。这始终取决于您的数据、索引、...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多