Pergunta

Eu estou tentando construir uma consulta que irá incluir uma coluna que indica se ou não um usuário tenha baixado um documento. Eu tenho uma tabela chamada HasDownloaded com as seguintes colunas: id, documentID, memberID. Descobrir se um usuário tiver baixado um específica documento é fácil; mas eu preciso gerar uma consulta onde os resultados será parecido com este:

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

A ID não é realmente importante; o que me interessa é se o documento já foi baixado (é NULL ou não).

Aqui está minha consulta:

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

O problema é que isto só irá retornar valores se existe uma entrada para o usuário especificado na tabela de HasDownloaded. Eu gostaria de manter este simples e só tem entradas no HasDownloaded para documentos que Tem foi baixado. Assim, se o usuário 1 tem baixado abc, bbb, e ccc, eu ainda quero ddd e eee a mostrar-se na tabela resultante, apenas com o ID como NULL. Mas a cláusula WHERE só me dá valores para os quais existe entradas.

Eu não sou muito de um especialista em SQL - existe um operador que vai me dar o que eu quero aqui? Eu deveria estar tomando uma abordagem diferente? Ou isso é impossível?

Foi útil?

Solução

Mover a condição na cláusula WHERE à condição de junção.

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

Isto é necessário sempre que você quer para se referir a uma esquerda juntar-ed mesa no que de outra forma seria a cláusula WHERE.

Outras dicas

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

seria a maneira normal de fazer isso. Alguns poderiam encurtar a:

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

Você pode, como Matt B. mostra, fazê-lo em sua condição JOIN - mas eu acho que é muito mais provável que as pessoas Confuse. Se você não entender por que movê-lo para o JOIN obras cláusula, então eu fortemente sugiro ficar longe dela.

@ Marcos: Eu entendo por que o JOIN sintaxe funciona, mas obrigado pelo aviso. Eu acho que sua sugestão é mais intuitivo. Eu estava curioso para ver o que era mais eficiente. Então eu corri um teste rápido (isso foi bastante simplista, eu estou com medo, mais de apenas 14 linhas e 10 ensaios):

Na condição de junção:

AND HasDownloaded.memberID = @memberID
  • tempo de processamento do cliente: 4.6
  • Total de tempo de execução: 35,5
  • tempo de espera nas respostas do servidor: 30,9

Na cláusula WHERE:

WHERE HasDownloaded.memberId IS NULL OR HasDownloaded.memberId = @memberId
  • tempo de processamento do cliente: 7.7
  • Total de tempo de execução: 27,7
  • tempo de espera nas respostas do servidor: 22,0

Parece que a cláusula WHERE é sempre tão ligeiramente mais eficiente. Interessante! Mais uma vez, graças a ambos por sua ajuda.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top