MySQL" NO ESTÁ EN " consulta


Quería ejecutar una consulta simple para mostrar todas las filas de Table1 donde un valor de columna principal no está presente en una columna en otra tabla (Table2).

He intentado usar:

SELECT * FROM Table1 WHERE Table1.principal NOT IN Table2.principal

Esto es en cambio lanzar un error de sintaxis. La búsqueda de Google me llevó a foros donde la gente decía que MySQL no es compatible con NOT IN y que hay que usar algo extremadamente complejo. ¿Es esto cierto? ¿O estoy cometiendo un terrible error?

 161
Author: Dominic Rodger, 2009-10-05

5 answers

Para usar EN, debe tener un conjunto, use esta sintaxis en su lugar:

SELECT * FROM Table1 WHERE Table1.principal NOT IN (SELECT principal FROM table2)
 281
Author: Julien Lebosquain,
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
2009-10-05 10:29:32

La opción de subconsulta ya ha sido respondida, pero tenga en cuenta que en muchos casos un LEFT JOIN puede ser una forma más rápida de hacer esto:

SELECT table1.*
FROM table1 LEFT JOIN table2 ON table2.principal=table1.principal
WHERE table2.principal IS NULL

Si desea verificar varias tablas para asegurarse de que no esté presente en ninguna de las tablas (como en el comentario de SRKR), puede usar esto:

SELECT table1.*
FROM table1
LEFT JOIN table2 ON table2.name=table1.name
LEFT JOIN table3 ON table3.name=table1.name
WHERE table2.name IS NULL AND table3.name IS NULL
 155
Author: Lukáš Lalinský,
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
2011-08-09 18:49:04

NOT IN vs. NOT EXISTS vs. LEFT JOIN / IS NULL in MySQL

MySQL, así como todos los demás sistemas excepto SQL Server, es capaz de optimizar LEFT JOIN / IS NULL devolver FALSE tan pronto se encuentre el valor coincidente, y es el único sistema que se preocupó por documentar este comportamiento. [...] Ya que MySQL no es capaz de usar HASH y MERGE unirse a los algoritmos, la única ANTI JOIN es capaz de es el NESTED LOOPS ANTI JOIN

[…]

Esencialmente, [NOT IN] es exactamente el mismo plan que LEFT JOIN / IS NULL usos, a pesar de que estos planes son ejecutados por las diferentes ramas de código y se ven diferentes en los resultados de EXPLAIN. Los algoritmos son de hecho los mismos de hecho y las consultas se completan en el mismo tiempo.

[…]

Es difícil decir la razón exacta de [caída de rendimiento cuando se usa NOT EXISTS], dado que esta caída es lineal y no parece depender de los datos distribución, número de valores en ambas tablas, etc., siempre y cuando ambos campos estén indexados. Dado que hay tres piezas de código en MySQL que esencialmente hacen un trabajo, es posible que el código responsable de EXISTS haga algún tipo de comprobación adicional que toma tiempo adicional.

[…]

MySQL puede optimizar los tres métodos para hacer una especie de NESTED LOOPS ANTI JOIN. […] Sin embargo, estos tres métodos generan tres planes diferentes que son ejecutados por tres piezas diferentes de codificar. El código que ejecuta EXISTS predicado es aproximadamente un 30% menos eficiente [{]

Es por eso que la mejor manera de buscar valores faltantes en MySQL es usando un LEFT JOIN / IS NULL o NOT IN en lugar de NOT EXISTS.

(énfasis añadido)

 34
Author: engin,
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
2012-02-15 07:19:26

Desafortunadamente, parece ser un problema con el uso de MySQL de la cláusula" NOT IN", la captura de pantalla a continuación muestra la opción de sub-consulta que devuelve resultados incorrectos:

mysql> show variables like '%version%';
+-------------------------+------------------------------+
| Variable_name           | Value                        |
+-------------------------+------------------------------+
| innodb_version          | 1.1.8                        |
| protocol_version        | 10                           |
| slave_type_conversions  |                              |
| version                 | 5.5.21                       |
| version_comment         | MySQL Community Server (GPL) |
| version_compile_machine | x86_64                       |
| version_compile_os      | Linux                        |
+-------------------------+------------------------------+
7 rows in set (0.07 sec)

mysql> select count(*) from TABLE_A where TABLE_A.Pkey not in (select distinct TABLE_B.Fkey from TABLE_B );
+----------+
| count(*) |
+----------+
|        0 |
+----------+
1 row in set (0.07 sec)

mysql> select count(*) from TABLE_A left join TABLE_B on TABLE_A.Pkey = TABLE_B.Fkey where TABLE_B.Pkey is null;
+----------+
| count(*) |
+----------+
|      139 |
+----------+
1 row in set (0.06 sec)

mysql> select count(*) from TABLE_A where NOT EXISTS (select * FROM TABLE_B WHERE TABLE_B.Fkey = TABLE_A.Pkey );
+----------+
| count(*) |
+----------+
|      139 |
+----------+
1 row in set (0.06 sec)

mysql> 
 7
Author: Legna,
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
2012-10-11 16:28:25

Tenga cuidado NOT IN no es un alias para <> ANY, sino para <> ALL!

Http://dev.mysql.com/doc/refman/5.0/en/any-in-some-subqueries.html

SELECT c FROM t1 LEFT JOIN t2 USING (c) WHERE t2.c IS NULL

No puede sustituirse por

SELECT c FROM t1 WHERE c NOT IN (SELECT c FROM t2)

Debes usar

SELECT c FROM t1 WHERE c <> ANY (SELECT c FROM t2)
 5
Author: user4554358,
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
2015-02-11 10:52:32