MySql, как объединить запрос LEFT JOIN с запросом NOT IN

Мне нужно совместить LEFT JOIN запрос с NOT IN запрос и должны получить значения результата из этих запросов. Я получил правильные результаты при использовании этих двух запросов по отдельности.

У меня две таблицы скорее всего user а также answer

user Таблица

user_id 
1
2
3
4
5

answer Таблица

user_id     date 
1           2015-10-15 21:23:14
2           2015-10-15 20:23:14
3           2015-11-11 16:23:14

LEFT JOIN запрос:

SELECT user.user_id
FROM user 
LEFT JOIN answer 
  ON user.user_id = answer.user_id 
WHERE DATEDIFF(NOW(),answer.date) > 5

Этот запрос возвращает результат user_id 1,2.

NOT IN запрос:

SELECT user.user_id 
FROM user 
WHERE user.user_id NOT IN (SELECT answer.user_id FROM answer)

Этот запрос возвращает результат user_ids 4, 5.

Мне нужно объединить эти два запроса в один запрос, поэтому я попытался с этими двумя запросами ниже:

 SELECT user.user_id 
 FROM user 
 LEFT JOIN answer 
   ON user.user_id = answer.user_id 
 WHERE (DATEDIFF(NOW(),answer.date) > 5 
   AND user.user_id NOT IN (SELECT answer.user_id FROM answer))

а также

 SELECT user.user_id 
 FROM user 
 LEFT JOIN answer 
   ON user.user_id = answer.user_id 
 WHERE user.user_id NOT IN (SELECT answer.user_id FROM answer) 
   AND DATEDIFF(NOW(),answer.date) > 5 

Но они возвращаются пустыми user_id,

редактировать

Ожидаемый результат должен содержать значения 1,2,4,5

3 ответа

Решение

Если ваше значение собирается объединить 2 выбора вместе
Попробуйте Union All / Союз:

SELECT * FROM 
(
SELECT [WITH YOUR LEFT JOIN STATEMENT]
UNION 
SELECT [WITH YOUR NOT IN STATEMENT]
) ResultTABLE

Ваш запрос правильный, но вы должны просто заменить AND с OR:

SELECT user.user_id 
FROM user 
LEFT JOIN answer 
    ON user.user_id = answer.user_id 
WHERE user.user_id NOT IN (SELECT answer.user_id FROM answer) 
    OR DATEDIFF(NOW(),answer.date) > 5 

Здесь вы можете найти рабочее решение: http://sqlfiddle.com/

Если вы обратитесь к таблице ответов в WHERE оговорка answer.date будет ограничено ненулевым значением, что делает LEFT JOIN вести себя как обычное соединение. Переместить условие в ON условие для извлечения всех пользователей, а также, возможно, соответствующие строки в answers:

 SELECT user.user_id
 FROM user u
 LEFT JOIN answer a ON u.user_id = a.user_id
                    AND DATEDIFF(NOW(),a.date) < 5
    ;

Редактировать: после редактирования вопроса кажется, что ОП хочет объединить записи с несуществующим ответом ИЛИ answer.date too old/young:

 SELECT user.user_id
 FROM user u
 LEFT JOIN answer a ON u.user_id = a.user_id
 WHERE a.date IS NULL               -- no answer record
    OR DATEDIFF(NOW(),a.date) > 5   -- too old answer record
    ;

Окончательная версия: поскольку ОП хочет найти пользователей, у которых нет (недавнего) ответа, запрос можно упростить до:

SELECT user.user_id
FROM user u
WHERE NOT EXISTS (
    SELECT * FROM answer a
    WHERE a.user_id = u.user_id
    AND DATEDIFF(NOW(), a.date) <= 5
    );
Другие вопросы по тегам