Pregunta

Estoy intentando construir una consulta que incluirá una columna que indica si un usuario ha descargado un documento. Tengo una tabla llamada HasDownloaded con las siguientes columnas: id, documentID, memberID. Averiguar si un usuario ha descargado un documento específico es fácil; pero necesito generar una consulta donde los resultados se verán así:

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

La ID no es realmente importante; lo que me interesa es si el documento se ha descargado (es NULL o no).

Aquí está mi consulta:

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

El problema es que esto solo devolverá valores si existe una entrada para el usuario especificado en la tabla HasDownloaded. Me gustaría mantener esto simple y solo tener entradas en HasDownloaded para los documentos que se han descargado . Entonces, si el usuario 1 ha descargado abc, bbb y ccc, todavía quiero que ddd y eee aparezcan en la tabla resultante, solo con el ID como NULL. Pero la cláusula WHERE solo me da valores para los cuales existen entradas.

No soy un experto en SQL, ¿hay algún operador que me dé lo que quiero aquí? ¿Debo estar tomando un enfoque diferente? ¿O es esto imposible?

¿Fue útil?

Solución

Mueva la condición en la cláusula WHERE a la condición de unión.

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

Esto es necesario siempre que desee consultar una tabla de la izquierda en lo que de otro modo sería la cláusula WHERE.

Otros consejos

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

sería la forma normal de hacerlo. Algunos lo acortarían a:

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

Usted puede, como lo muestra Matt B., hacerlo en su condición de ÚNETE, pero creo que eso es mucho más probable que confunda a la gente. Si no entiendes POR QUÉ funciona el cambio a la cláusula JOIN, te sugiero que te mantengas alejado de él.

@Mark: entiendo por qué funciona la sintaxis de JOIN, pero gracias por la advertencia. Creo que tu sugerencia es más intuitiva. Tenía curiosidad por ver cuál era más eficiente. Así que hice una prueba rápida (esto fue bastante simplista, me temo, en solo 14 filas y 10 pruebas):

En la condición de ÚNETE:

AND HasDownloaded.memberID = @memberID
  • Tiempo de procesamiento del cliente: 4.6
  • Tiempo total de ejecución: 35.5
  • Tiempo de espera en las respuestas del servidor: 30.9

En la cláusula WHERE:

WHERE HasDownloaded.memberId IS NULL OR HasDownloaded.memberId = @memberId
  • Tiempo de procesamiento del cliente: 7.7
  • Tiempo total de ejecución: 27.7
  • Tiempo de espera en las respuestas del servidor: 22.0

Parece que la cláusula WHERE es un poco más eficiente. ¡Interesante! Una vez más, gracias a los dos por su ayuda.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top