Помогите с 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 несколько более эффективно. Интересно! Еще раз спасибо вам обоим за помощь.