Mysql
 sql >> Database >  >> RDS >> Mysql

MySQL "NOT IN" interroga 3 tabelle

Evita NOT IN come la peste se

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

potrebbe mai contenere NULL. Invece, usa NOT EXISTS o Left Joins

usa join espliciti, non join in stile anni '80 usando WHERE clausola

Per illustrare la miseria di NOT IN:

SQL NOT IN () pericolo

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
);

Pezzo1:

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

** 3 righe, come previsto **

Pezzo2:

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);

nessuna riga, eh?

Ovviamente questo è "sbagliato". Nasce dall'uso da parte di SQL della logica a tre valori, guidata dall'esistenza di NULL, un non valore che indica informazioni mancanti (o SCONOSCIUTE). Con NOT IN, Chunk2 è tradotto in questo modo:

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

Ciò equivale a:

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

L'espressione "status=NULL" restituisce UNKNOWN e, secondo le regole della logica a tre valori, NOT UNKNOWN restituisce anche UNKNOWN. Di conseguenza, tutte le righe vengono filtrate e la query restituisce un set vuoto.

Le possibili soluzioni includono:

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

oppure usa not exists