SQL: сравнить 2 таблицы и указать, были ли найдены данные

#sql #datetime #mariadb #subquery #left-join

#sql #datetime #mariadb #подзапрос #левое соединение

Вопрос:

Я новичок, когда дело доходит до SQL, поэтому простите меня, если это глупый вопрос.

У меня есть 2 таблицы, одна со списком пользователей, а другая содержит данные истории электронной почты.

Таблица пользователей:

 userID fName  lName ...
1      John   Smith
2      Jane   Doe
3      Kevin  Cooper
  

Таблица истории сообщений электронной почты:

 emailID userID subject sendDate ...
1       6      welcome 2020-10-17
2       3      hello   2020-10-20
3       7      welcome 2020-10-23
  

Я хочу выполнить какой-то оператор select, который сравнивал бы каждого клиента в таблице 1 с каждым электронным письмом в таблице 2 на основе какого-либо поискового запроса (в данном случае, когда subject = «hello» и SendDate = «2020-10-20» и возвращал бы что-то вроде этого:

Возвращенный запрос:

 userID  fName  lName  ...  emailSent?
1       John   Smith  ...  No
2       Jane   Doe    ...  No
3       Kevin  Cooper ...  Yes
  

Ответ №1:

Один из вариантов использует exists и коррелированный подзапрос:

 select u.*, 
    exists (
        select 1
        from emailhistory eh
        where eh.userid = u.userid and eh.subject = 'hello' and eh.senddate = '2020-20-20'
    ) emailSent
from users u
  

Это дает вам 0 / 1 значения в столбце emailSent , где 1 указывает, что совпадение существует. По сравнению с left join подходом, преимуществом является то, что он не «умножает» пользовательские строки, если в таблице истории найдено более одного совпадения.

Для повышения производительности рассмотрите индекс on emailhistory(userid, subject, senddate) .

Ответ №2:

Вы можете слева присоединиться к таблице электронной почты, указав свои критерии даты и темы в предложении where:

 SELECT
  u.userid,
  u.fname,
  u.lname,
  case when eh.emailid is null then 'No' else 'Yes' end as emailsent
FROM
  users u
  LEFT JOIN 
  emailhistory eh 
  ON 
    u.userid = eh.emailid AND
    eh.subject = 'hello' AND
    eh.senddate = '2020-10-20'
  

Это концептуально фильтрует таблицу электронной почты только до этой темы и дня, а затем объединяет эти записи в таблицу users. Вы получаете каждую строку от пользователей и только строки из emailhistory, которые соответствуют идентификатору пользователя, а также имеют эту тему / дату. Затем вы можете проверить, является ли идентификатор электронной почты (ключ соединения) нулевым или нет; единственный способ, которым он может быть нулевым, — это если в эту дату этому пользователю не было отправлено электронное письмо с этой темой