2012-01-18 100 views
0

我有3個InnoDB表:電子郵件網站訂閱MySQL查詢(與連接和虛擬值)

電子郵件表具有idemail列。

網站表具有idaddress列。

訂閱表有idemail_idwebsite_id列。

我想要做的是提供一封電子郵件,並返回一個列表addresssubscribed。前者是網站表中所有地址的列表,如果提供的電子郵件地址在訂閱中發生,表中的表設置爲該網站的website_id,否則爲0,否則爲0。但是我願意保留所有的網站,即使用戶沒有找到。

我被卡住的一點是我應該在虛擬列subscribed的值從0變爲1時,該電子郵件具有該記錄。

這是我的查詢到目前爲止。有人知道怎麼做這個嗎?

SELECT `address`, "0" AS `subscribed` 
/* 0 becomes 1 for the websites email has subscribed to */ 
FROM `websites` a 
LEFT JOIN (
    SELECT s.`website_id` FROM `subscriptions` s 
    RIGHT JOIN (
     SELECT `id` AS `email_id` FROM `emails` 
     WHERE `email`='[email protected]' LIMIT 1) e 
    ON s.`email_id`=e.`email_id`) l 
ON l.`website_id`=a.`id` 

這裏是爲subscribed列期望的值輸出示例:

  • 如果emails表中沒有找到郵件中的所有行獲得值0
  • 如果發現電子郵件在emails表...
    • 如果沒有subscriptions表中的所有行獲取值0
    • 如果在subscriptions表中找到,相應的地址行獲得價值1

讓我知道,如果我不能wxplain很好。有人知道我在查詢中應該改變什麼嗎?

在此先感謝。

+0

您應該避免使用RIGHT JOIN。他們不被認爲是很好的風格,根據我的經驗,MySQL運行它們的速度比等效的左連接慢。 – Poodlehat 2012-01-18 16:11:40

+0

謝謝。我通常也不會使用它們,但是我迷失在這個查詢中,所以想也許......但是,感謝Joe,問題解決了。我擺脫了正確的加入:) – inhan 2012-01-18 20:28:34

回答

2
SELECT w.address, CASE WHEN s.id IS NULL THEN 0 ELSE 1 END AS subscribed 
    FROM websites w 
     LEFT JOIN subscriptions s 
      INNER JOIN emails e 
       ON s.email_id = e.id 
        AND e.email = '[email protected]' 
      ON w.id = s.website_id 

你也可以用這種方式來提供訂閱的價值,這有點簡潔但也不太明顯。

SELECT w.address, COALESCE(s.id/s.id, 0) AS subscribed 
    FROM websites w 
     LEFT JOIN subscriptions s 
      INNER JOIN emails e 
       ON s.email_id = e.id 
        AND e.email = '[email protected]' 
      ON w.id = s.website_id 
+0

非常感謝。你的第一個代碼很好用,但我更喜歡第二個代碼。後者的問題是它返回浮點數,所以我對你的第一行做了一些補充:'SELECT w.address,CAST(COALESCE(s.id/s.id,0)AS SIGNED)AS訂閱' – inhan 2012-01-18 17:23:45