Seleccionar filas que no están presentes en otra tabla
Tengo dos tablas de postgresql:
table name column names
----------- ------------------------
login_log ip | etc.
ip_location ip | location | hostname | etc.
Quiero obtener todas las direcciones IP de login_log
que no tienen una fila en ip_location
.
He intentado esta consulta, pero arroja un error de sintaxis.
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`
También me pregunto si esta consulta (con ajustes para que funcione) es la consulta que mejor funciona para este propósito.
4 answers
Hay básicamente 4 técnicas para esta tarea, todas ellas SQL estándar.
NOT EXISTS
A menudo, esto es más rápido en Postgres.
SELECT ip
FROM login_log l
WHERE NOT EXISTS (
SELECT -- mostly irrelevant what's here; might just be empty in pg
FROM ip_location i
WHERE l.ip = i.ip
);
También considere:
LEFT JOIN / IS NULL
A veces esto es más rápido. A menudo más corto.
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
Corto. No tan fácilmente integrado en más complejo consulta.
SELECT ip
FROM login_log
EXCEPT ALL -- ALL, to keep duplicate rows and make it faster
SELECT ip
FROM ip_location;
Tenga en cuenta que ( por documentación):
Los duplicados se eliminan a menos que se utilice
EXCEPT ALL
.
Normalmente, querrás la palabra clave ALL
. Si no te importa, sigue usándolo porque hace que la consulta sea más rápida.
NOT IN
Solo es bueno sin valores NULL o si sabes manejar NULL correctamente! Yo no lo usaría para este propósito. El rendimiento puede deteriorarse con más grande tabla.
SELECT ip
FROM login_log
WHERE ip NOT IN (
SELECT DISTINCT ip -- DISTINCT is optional
FROM ip_location
);
NOT IN
lleva una" trampa " para NULL
valores a cada lado:
Pregunta similar sobre dba.SE dirigido a MySQL:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-05 17:22:35
A.) El comando NO EXISTE, te falta la 'S'.
B.) NO usar en su lugar
SELECT ip
FROM login_log
WHERE ip NOT IN (
SELECT ip
FROM ip_location
)
;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-14 15:30:55
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 ;
Aquí la tabla testcases1 contiene todos los datos y executions1 la tabla contiene algunos datos entre la tabla testcases1. Estoy recuperando solo los datos que no están presentes en la tabla exections1. (e incluso yo estoy dando algunas condiciones en el interior que usted también puede dar.) especificar la condición que no debe estar allí en la recuperación de datos debe estar dentro de corchetes.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-04 08:29:25
Esto también se puede intentar...
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-19 00:03:44