sql >> Base de Datos >  >> RDS >> Mysql

Consulta MySQL "NO EN" 3 tablas

Evite NOT IN como la peste si

SELECT ID_Courses FROM Evaluation where `NAME`='JOHN' and Year=1

nunca podría contener NULL. En su lugar, use NOT EXISTS o Left Joins

use uniones explícitas, no uniones al estilo de los años 80 usando WHERE cláusula

Para ilustrar la miseria de NOT IN:

SQL NO EN () peligro

create table mStatus
(   id int auto_increment primary key,
    status varchar(10) not null
);
insert mStatus (status) values ('single'),('married'),('divorced'),('widow');

create table people
(   id int auto_increment primary key,
    fullName varchar(100) not null,
    status varchar(10)  null
);

Fragmento 1:

truncate table people;
insert people (fullName,`status`) values ('John Henry','single');
select * from mstatus where `status` not in (select status from people);

** 3 filas, como se esperaba **

Fragmento 2:

truncate table people;
insert people (fullName,`status`) values ('John Henry','single'),('Kim Billings',null);
select * from mstatus where status not in (select status from people);

sin filas, ¿eh?

Obviamente esto es 'incorrecto'. Surge del uso de SQL de la lógica de tres valores, impulsada por la existencia de NULL, un valor que indica información faltante (o DESCONOCIDA). Con NOT IN, Chunk2 se traduce así:

status NOT IN ('married', 'divorced', 'widowed', NULL)

Esto es equivalente a:

NOT(status='single' OR status='married' OR status='widowed' OR status=NULL)

La expresión "status=NULL" se evalúa como DESCONOCIDO y, según las reglas de la lógica de tres valores, NO DESCONOCIDO también se evalúa como DESCONOCIDO. Como resultado, todas las filas se filtran y la consulta devuelve un conjunto vacío.

Las posibles soluciones incluyen:

select s.status
from mstatus s
left join people p
on p.status=s.status
where p.status is null

o use not exists