sql - left - right join oracle
Ayuda con un WHERE en una consulta SQL LEFT JOIN (3)
Estoy intentando construir una consulta que incluirá una columna que indique si un usuario ha descargado un documento o no. 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 vean así:
name id
----------------------
abc NULL
bbb 2
ccc 53
ddd NULL
eee 13
La identificación no es realmente importante; lo que me interesa es si el documento se ha descargado (si es NULO 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 tengo entradas en HasDownloaded para documentos que se han descargado. Entonces, si el usuario 1 ha descargado abc, bbb y ccc, aún 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 que existen entradas.
No soy experto en SQL, ¿hay un operador que me dé lo que quiero aquí? ¿Debo tomar un enfoque diferente? ¿O es esto imposible?
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 referirse a una tabla left-join-ed en lo que de otro modo sería la cláusula WHERE.
@ Mark: entiendo por qué funciona la sintaxis 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 realicé una prueba rápida (me temo que era bastante simplista en solo 14 filas y 10 intentos):
En la condición JOIN:
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 ligeramente más eficiente. ¡Interesante! Una vez más, gracias a ambos por su ayuda.
WHERE HasDownloaded.memberId IS NULL OR HasDownloaded.memberId = @memberId
sería la forma normal de hacer eso. Algunos lo acortan a:
WHERE COALESCE(HasDownloaded.memberId, @memberId) = @memberId
Puedes, como muestra Matt B., hacerlo en tu condición de JOIN, pero creo que es mucho más probable que confunda a la gente. Si no entiende POR QUÉ moverlo a la cláusula JOIN funciona, entonces le sugiero que se mantenga alejado de él.