J'ai deux tables postgresql:
table name column names
----------- ------------------------
login_log ip | etc.
ip_location ip | location | hostname | etc.
Je veux obtenir chaque adresse IP de login_log
qui n'a pas de ligne dans ip_location
.
J'ai essayé cette requête, mais une erreur de syntaxe est émise.
SELECT login_log.ip
FROM login_log
WHERE NOT EXIST (SELECT ip_location.ip
FROM ip_location
WHERE login_log.ip = ip_location.ip)
ERROR: syntax error at or near "SELECT" LINE 3: WHERE NOT EXIST (SELECT ip_location.ip`
Je me demande aussi si cette requête (avec les ajustements nécessaires) est la requête la plus performante à cet effet.
Il existe essentiellement 4 techniques pour cette tâche, toutes en SQL standard.
NOT EXISTS
Souvent le plus rapide dans Postgres.
SELECT ip
FROM login_log l
WHERE NOT EXISTS (
SELECT -- SELECT list mostly irrelevant; can just be empty in Postgres
FROM ip_location
WHERE ip = l.ip
);
Considérez également:
LEFT JOIN / IS NULL
Parfois c'est le plus rapide. Souvent le plus court. Il en résulte souvent le même plan de requête que NOT EXISTS
.
SELECT l.ip
FROM login_log l
LEFT JOIN ip_location i USING (ip) -- short for: ON i.ip = l.ip
WHERE i.ip IS NULL;
EXCEPT
Court. Pas aussi facilement intégré dans des requêtes plus complexes.
SELECT ip
FROM login_log
EXCEPT ALL -- "ALL" keeps duplicates and makes it faster
SELECT ip
FROM ip_location;
Notez que ( par documentation ):
les doublons sont éliminés sauf si
EXCEPT ALL
est utilisé.
En règle générale, vous souhaiterez le mot clé ALL
. Si vous ne vous en souciez pas, utilisez-le quand même car cela rend la requête plus rapide.
NOT IN
Seulement bon sans les valeurs NULL
ou si vous savez manipuler NULL
correctement. Je voudrais pas l'utiliser à cette fin. Les performances peuvent se détériorer avec des tables plus grandes.
SELECT ip
FROM login_log
WHERE ip NOT IN (
SELECT DISTINCT ip -- DISTINCT is optional
FROM ip_location
);
NOT IN
comporte un "piège" pour les valeurs NULL
de chaque côté:
Question similaire sur dba.SE ciblée sur MySQL:
A.) La commande est NOT EXISTS, il vous manque le 'S'.
B.) Utilisez NOT IN à la place
SELECT ip
FROM login_log
WHERE ip NOT IN (
SELECT ip
FROM ip_location
)
;
cela peut aussi être essayé ...
SELECT l.ip, tbl2.ip as ip2, tbl2.hostname
FROM login_log l
LEFT JOIN (SELECT ip_location.ip, ip_location.hostname
FROM ip_location
WHERE ip_location.ip is null)tbl2
SELECT *
FROM testcases1 t
WHERE NOT EXISTS (
SELECT 1
FROM executions1 i
WHERE t.tc_id = i.tc_id and t.pro_id=i.pro_id and pro_id=7 and version_id=5
) and pro_id=7 ;
Ici, la table testcases1 contient toutes les données et la table executions1 contient quelques données parmi la table testcases1. Je ne récupère que les données qui ne sont pas présentes dans la table exections1. (et même je donne certaines conditions à l'intérieur que vous pouvez aussi donner.) spécifiez une condition qui ne devrait pas être là pour récupérer des données devrait être entre crochets.