Disons que j'ai le schéma et les données suivants:
create table images(
id int not null
);
insert into images values(1), (2), (3), (4), (6), (8);
Je souhaite effectuer une requête comme:
select id from images where id not exists in(4, 5, 6);
Mais ça ne marche pas. Le cas ci-dessus doit renvoyer 5
, car il n'existe pas dans les enregistrements de la table.
Vous pouvez utiliser une jointure externe contre une liste values
(similaire à la réponse de Martin mentionnée ci-dessus):
select t.id
from (
values (4),(5),(6)
) as t(id)
left join images i on i.id = t.id
where i.id is null;
ou un not exists
avec le constructeur de ligne:
select *
from (
values (4),(5),(6)
) as v(id)
where not exists (select *
from images i
where i.id = v.id);
Si vous le souhaitez, vous pouvez également placer la clause values
dans un CTE pour faciliter la lecture de la requête finale:
with v (id) as (
values (4),(5),(6)
)
select v.id
from v
left join images i on i.id = v.id
where i.id is null;
Lorsque vous utilisez EXCEPT
comme @ Martin fourni , n'oubliez pas de le faire EXCEPT
ALL
, sauf si vous voulez payer un petit supplément pour essayer de plier les doublons.
BTW, une expression VALUES
peut se suffire à elle-même:
VALUES (4),(5),(6)
EXCEPT ALL
SELECT id FROM images;
Mais vous obtenez les noms de colonnes par défaut de cette façon.
Pour une longue liste de valeurs, il peut être plus commode de la fournir sous forme de tableau et de ne pas lâcher. Syntaxe plus courte:
SELECT * FROM unnest('{4,5,6}'::int[]) id
EXCEPT ALL
SELECT id FROM images;
Il existe quelques techniques de base pour la tâche:
Utilisez simplement une deuxième table et rejoignez-les.
create table images1(
id int not null
);
create table images2(
id int not null
);
insert into images1 values(1), (2), (3), (4), (6), (8);
insert into images2 values (4), (5), (6);
SELECT i2.ID
FROM images2 i2
LEFT JOIN images1 i1
ON i1.ID = i2.ID
WHERE i1.ID IS NULL