Es bastante simple, cuando le coges el tranquillo:
SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND S.S_Id NOT IN(SELECT e.S_Id -- take this line
FROM ENROLLMENT e
WHERE e.Mark < 70);
Esa línea básicamente compara S.S_Id
con todos los e.S_Id
valores que provienen de la subconsulta.
Ahora cámbialo a NOT EXISTS
y poner una verificación de igualdad S.S_Id = e.S_Id
, dentro de la subconsulta:
SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND NOT EXISTS (SELECT e.S_Id
FROM ENROLLMENT e
WHERE (e.Mark < 70) -- if this is complex, you'll need parentheses
AND S.S_Id = e.S_Id);
El cambio menor posible es darse cuenta de que (SELECT e.S_Id ...
realmente no necesita el e.S_Id
. Subconsultas con EXISTS
y NOT EXISTS
simplemente verifique si hay filas devueltas o no y los valores de las columnas no importan. Puedes poner SELECT *
o una constante allí (SELECT 1
es común) o SELECT NULL
o incluso SELECT 1/0
(¡Sí, eso funcionará!):
SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND NOT EXISTS (SELECT 1
FROM ENROLLMENT e
WHERE e.Mark < 70
AND S.S_Id = e.S_Id);
Otra consideración importante es que cuando realiza la conversión de esta manera, el (aparentemente equivalente) NOT EXISTS
y NOT IN
las escrituras de una consulta son realmente equivalentes solo si ambos S_Id
las columnas no son anulables. Si el e.S_Id
la columna es anulable, el NOT IN
puede dar como resultado que la consulta completa no devuelva ninguna fila (porque x NOT IN (a, b, c, ...)
es equivalente a x<>a AND x<>b AND ...
y esa condición no puede ser verdadera cuando uno de los a,b,c...
es NULL
.)
Por razones similares, obtendrá resultados diferentes si s.S_Id
es anulable (eso no es muy probable en este caso, ya que probablemente sea la clave principal, pero en otros casos es importante).
Así que casi siempre es mejor usar NOT EXISTS
, ya que se comporta de manera diferente incluso si cualquiera de las columnas admite valores NULL (el S.S_Id = e.S_Id
check descartará las filas con nulo anterior) y, por lo general, este comportamiento es el deseado. Hay muchos detalles en la pregunta: NO EN vs NO EXISTE
, en la respuesta de @Martin Smith. También encontrará formas de convertir el NOT IN
a NOT EXISTS
y mantener el comportamiento relacionado nulo (desagradable).