Помогите с WHERE в SQL-запросе LEFT JOIN

Я пытаюсь создать запрос, который будет включать столбец, указывающий, загрузил ли пользователь документ. У меня есть таблица с именем HasDownloaded со следующими столбцами: id, documentID, memberID. Узнать, загрузил ли пользователь конкретный документ, легко; но мне нужно сгенерировать запрос, где результаты будут выглядеть так:

name              id
----------------------
abc               NULL
bbb               2
ccc               53
ddd               NULL
eee               13

Идентификатор не очень важен; меня интересует, был ли документ загружен (NULL или нет).

Вот мой запрос:

SELECT Documents.name, HasDownloaded.id FROM Documents
LEFT JOIN HasDownloaded ON HasDownloaded.documentID = Documents.id
WHERE HasDownloaded.memberID = @memberID

Проблема в том, что он будет возвращать значения только в том случае, если существует запись для указанного пользователя в таблице HasDownloaded. Я хотел бы сохранить это простым и иметь записи в HasDownloaded только для документов, которые были загружены. Так что, если пользователь 1 загрузил abc, bbb и ccc, я все еще хочу, чтобы ddd и eee отобразились в полученной таблице, просто с идентификатором NULL. Но предложение WHERE дает только значения, для которых существуют записи.

Я не большой эксперт по SQL - есть ли оператор, который даст мне то, что я хочу здесь? Должен ли я придерживаться другого подхода? Или это невозможно?

3 ответа

Решение

Переместите условие в предложении WHERE в условие соединения.

SELECT Documents.name, HasDownloaded.id FROM Documents
LEFT JOIN HasDownloaded ON HasDownloaded.documentID = Documents.id 
  AND HasDownloaded.memberID = @memberID 

Это необходимо всякий раз, когда вы хотите сослаться на левую соединенную таблицу в том, что иначе было бы предложением WHERE.

WHERE HasDownloaded.memberId IS NULL OR HasDownloaded.memberId = @memberId

было бы нормальным способом сделать это. Некоторые сократили бы это до:

WHERE COALESCE(HasDownloaded.memberId, @memberId) = @memberId

Вы можете, как показывает Мэтт Б., делать это в состоянии JOIN - но я думаю, что это намного больше смущает людей. Если вы не понимаете, ПОЧЕМУ перемещение этого предложения в предложение JOIN работает, то я настоятельно рекомендую держаться подальше от него.

@Mark: я понимаю, почему синтаксис JOIN работает, но спасибо за предупреждение. Я думаю, что ваше предложение более интуитивно понятно. Мне было любопытно посмотреть, что было более эффективным. Итак, я провел быстрый тест (боюсь, это было довольно упрощенно, всего за 14 строк и 10 испытаний):

В состоянии СОЕДИНЕНИЯ:

AND HasDownloaded.memberID = @memberID
  • Время обработки клиента: 4.6
  • Общее время исполнения: 35,5
  • Время ожидания ответов сервера: 30,9

В предложении WHERE:

WHERE HasDownloaded.memberId IS NULL OR HasDownloaded.memberId = @memberId
  • Время обработки клиента: 7,7
  • Общее время исполнения: 27,7
  • Время ожидания ответов сервера: 22,0

Похоже, что предложение WHERE несколько более эффективно. Интересно! Еще раз спасибо вам обоим за помощь.

Другие вопросы по тегам