2016-04-07 62 views
0

我得到這個表:MySql的希望丟棄結果左加入

用戶

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

郵件

​​

Ref_Users_Mails

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

,我想下面的結果: 讓所有的用戶 從國家集合 不是從組國家 收到的郵件與此mailIds ,並沒有與其他mailIds

例如收到的郵件: 全部從日本和美國沒有用戶 得到了郵件1並沒有收到2.​​

==>結果應該只是'喬',但我設法得到'喬'和'本'(因爲'本'也有郵件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 | 
+0

*所有來自日本的用戶,而不是美國的* - 它不等於* *來自日本的所有用戶**? – splash58

+0

這會呈現爲INNER JOIN – Strawberry

+0

我認爲數據集不足以正確代表問題,而且解釋並不十分清楚。如果您願意,可以考慮遵循以下簡單的兩步操作步驟:1.如果您尚未這樣做,請提供適當的DDL(和/或sqlfiddle),以便我們可以更輕鬆地複製問題。 2.如果您尚未這樣做,請提供與步驟1中提供的信息相對應的所需結果集。 – Strawberry

回答

0

要具有國家得到用戶的行= '日本',這是足夠:

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中爲UNIQUE,那麼我們可以使用聯合操作來獲取它。

 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 

如果我們有保障此查詢模式將工作的(user_id, mail_id)元組是Ref_Users_Mails UNIQUE

+0

感謝您的詳細解釋,做了訣竅,我學到了很多東西! – user2212726

+1

@ user2212726:對於那些需要它的情況,*反連接*模式是SQL工具帶中有用的工具。反連接是返回所有行的外連接,包括具有「匹配」的行和未找到匹配的行,然後是WHERE子句中用於排除具有「匹配」的行的謂詞。它只返回沒有找到匹配的行。 – spencer7593