MySql希望丢弃左连接的结果

时间:2016-04-07 15:55:34

标签: mysql

我得到了这张桌子:

用户

|id |Name  | country|
--------------
|1  | Ben   | Japan  |
|2  | Jo    | Japan  |
|3  | Sam   |   US   |

邮件

|id | subject|
--------------
|1  | Good   |
|2  | Bonus  |

Ref_Users_Mails

|user_id | mail_id|
-------------------
|   1    |    1   |
|   1    |    2   |
|   2    |    1   |
|   3    |    1   |

我希望得到以下结果: 得到所有用户 来自一组国家 不是来自一组国家 收到了这封mailIds的邮件 并且没有收到与其他mailIds的邮件

例如: 所有来自日本而非美国的用户 收到邮件1但未收到邮件2。

==>结果应该只是'Jo',但我设法得到'Jo'和'Ben'(因为'Ben'也有邮件Id 1)

如何过滤'Ben',因为他也收到了邮件Id 2?

这是我的疑问:

   SELECT * FROM Users
   LEFT JOIN Ref_Users_Mails
   ON Users.id = Ref_Users_Mails.user_id
   WHERE ( trim(Users.country) IN ( 'Japan' ) ) 
   AND ( trim(Users.country) NOT IN ( 'US' ) ) 
   AND ( trim(Ref_Users_Mails.mail_id) NOT IN ( 2 ) ) 
   ORDER BY Users.user_id;

结果:

|id |Name  | country|
--------------
|1  | Ben   | Japan  |
|2  | Jo    | Japan  |

通缉结果:

|id |Name  | country|
--------------
|2  | Jo    | Japan  |

1 个答案:

答案 0 :(得分:0)

要从包含country =' Japan'的用户获取行,这就足够了:

   SELECT u.id
        , u.name
        , u.country
     FROM Users u
    WHERE TRIM(u.country) IN ('Japan')  
    ORDER BY u.id

没有必要在u.country上添加另一个谓词。这不是必要的:

      AND TRIM(u.country) NOT IN ('US')

因为如果WHERE子句中的条件为真,我们保证是真的。

从该查询返回的集合中,我们只希望收到邮件的用户1.如果我们保证(user_id,mail_id)元组在Ref_Users_Mails中是唯一的,我们可以使用连接操作来获取这一点。

     JOIN Ref_Users_Mails r
       ON r.user_id = u.id
      AND r.mail_id = 1

如果我们还想排除已收到邮件2的用户,我们可以使用反连接模式。

     LEFT
     JOIN Ref_Users_Mails q
       ON q.user_id = u.id
      AND q.mail_id = 2
    WHERE q.user_id IS NULL 

所以,把所有这些放在一起:

   SELECT u.id
        , u.name
        , u.country
     FROM Users u
     JOIN Ref_Users_Mails r
       ON r.user_id = u.id
      AND r.mail_id = 1
     LEFT
     JOIN Ref_Users_Mails q
       ON q.user_id = u.id
      AND q.mail_id = 2
    WHERE q.id IS NULL 
      AND TRIM(u.country) IN ('Japan')  
    ORDER BY u.id 

还有其他查询模式将返回等效结果。例如,我们可以使用EXISTS和NOT EXISTS谓词。

   SELECT u.id
        , u.name
        , u.country
     FROM Users u
    WHERE TRIM(u.country) IN ('Japan')
      AND EXISTS 
          ( SELECT 1 
              FROM Ref_Users_Mails r
             WHERE r.user_id = u.id
               AND r.mail_id = 1
          )
      AND NOT EXISTS
          ( SELECT 1
              FROM Ref_Users_Mails q
             WHERE q.user_id = u.id
               AND q.mail_id = 2
          )
    ORDER BY u.id

如果我们在Ref_Users_Mails中保证(user_id, mail_id)元组是唯一的

,则此查询模式将有效