Помогите с WHERE на SQL-запросе LEFT JOIN - PullRequest
19 голосов
/ 20 октября 2008

Я пытаюсь создать запрос, который будет включать столбец, указывающий, загрузил ли пользователь документ. У меня есть таблица с именем 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 ]

37 голосов
/ 20 октября 2008

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

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

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

4 голосов
/ 20 октября 2008
WHERE HasDownloaded.memberId IS NULL OR HasDownloaded.memberId = @memberId

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

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

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

3 голосов
/ 20 октября 2008

@ Марк: Я понимаю, почему работает синтаксис 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 несколько более эффективно. Интересно! Еще раз спасибо вам обоим за помощь.

...