2012-01-18 4 views
0

У меня есть 3 таблицы InnoDB: электронные письма, сайты и подписки.MYSQL запрос (с соединениями и виртуальные ценности)

электронная почта стол имеет id и email столбцы.

сайты стол имеет id и address колонок.

подписки таблица имеет id, email_id и website_id столбцов.

Что мне нужно сделать, это отправить электронное письмо и вернуть стол с колонками address и subscribed. Первый - это список всех адресов в таблице , а последний получает значение 1, если указанный адрес электронной почты имеет место в таблице подписок с website_id, установленными на этом веб-сайте, или 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

Вы должны избегать использования ПРАВИЛЬНЫХ СОЕДИНЕНИЙ. Они не считаются хорошим стилем, и, по моему опыту, MySQL запускает их LOT медленнее, чем эквивалентное левое соединение. – Poodlehat

+0

Спасибо. Я, как правило, тоже не использовал их, но я потерялся в этом запросе, поэтому подумал, может быть ... но благодаря Джо проблема решена. Я избавился от правильного соединения :) – inhan

ответ

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

Смежные вопросы