Évitez NOT IN
comme la peste si
SELECT ID_Courses FROM Evaluation where `NAME`='JOHN' and Year=1
pourrait jamais contenir NULL. Utilisez plutôt NOT EXISTS ou Left Joins
utilisez des jointures explicites, et non des jointures de style années 1980 en utilisant WHERE
clause
Pour illustrer la misère de NOT IN :
Danger SQL NOT IN ()
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
);
Bloc1 :
truncate table people;
insert people (fullName,`status`) values ('John Henry','single');
select * from mstatus where `status` not in (select status from people);
** 3 rangées, comme prévu **
Morceau2 :
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);
pas de rangées, hein ?
Évidemment, c'est "incorrect". Il découle de l'utilisation par SQL d'une logique à trois valeurs, pilotée par l'existence de NULL, une non-valeur indiquant des informations manquantes (ou INCONNUES). Avec NOT IN, Chunk2, il est traduit comme ceci :
status NOT IN ('married', 'divorced', 'widowed', NULL)
Cela équivaut à :
NOT(status='single' OR status='married' OR status='widowed' OR status=NULL)
L'expression "status=NULL" est évaluée à UNKNOWN et, selon les règles de la logique à trois valeurs, NOT UNKNOWN est également évaluée à UNKNOWN. Par conséquent, toutes les lignes sont filtrées et la requête renvoie un ensemble vide.
Les solutions possibles incluent :
select s.status
from mstatus s
left join people p
on p.status=s.status
where p.status is null
ou utilisez not exists