Rechercher des ID dans une liste qui n'existent pas dans une table

19

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 devrait revenir 5, car il n'existe pas dans les enregistrements de la table.

Patrick D'appollonio
la source

Réponses:

23

Vous pouvez utiliser une jointure externe contre une valuesliste (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 existsensemble 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 mettre la valuesclause 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;
un cheval sans nom
la source
10

Une façon de le faire serait VALUESde créer une expression de table avec les identifiants à vérifier et EXCEPTà trouver ceux qui manquent.

SELECT id
FROM (VALUES(4),(5),(6)) V(id)
EXCEPT
SELECT id 
FROM images;
Martin Smith
la source
6

LorsqueEXCEPT vous utilisez comme @Martin fourni , n'oubliez pas de le faire EXCEPTALL, sauf si vous voulez payer un petit supplément pour essayer de plier les doublons.

BTW, une VALUESexpression 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 pratique de le fournir sous forme de tableau et de non unnest. 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:

Erwin Brandstetter
la source
0

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
dfundako
la source
3
Si vous exécutez une sélection simple et que vous créez une table juste pour cela, ce n'est peut-être pas la meilleure solution.
Patrick D'appollonio