Ответ 1
Чтобы использовать IN, вы должны иметь набор, вместо этого используйте этот синтаксис:
SELECT * FROM Table1 WHERE Table1.principal NOT IN (SELECT principal FROM table2)
Я хотел запустить простой запрос, чтобы выкинуть все строки Table1
, где главное значение столбца отсутствует в столбце в другой таблице (Table2
).
Я попытался использовать:
SELECT * FROM Table1 WHERE Table1.principal NOT IN Table2.principal
Вместо этого возникает ошибка синтаксиса. Поиск Google привел меня на форумы, где люди говорили, что MySQL не поддерживает NOT IN
, и что-то чрезвычайно сложное нужно использовать. Это правда? Или я совершаю ужасную ошибку?
Чтобы использовать IN, вы должны иметь набор, вместо этого используйте этот синтаксис:
SELECT * FROM Table1 WHERE Table1.principal NOT IN (SELECT principal FROM table2)
Опция подзапроса уже ответила, но обратите внимание, что во многих случаях LEFT JOIN
может быть более быстрым способом:
SELECT table1.*
FROM table1 LEFT JOIN table2 ON table2.principal=table1.principal
WHERE table2.principal IS NULL
Если вы хотите проверить несколько таблиц, чтобы убедиться, что они не присутствуют ни в одной из таблиц (например, в комментарии SRKR), вы можете использовать это:
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
MySQL, а также все другие системы, кроме SQL Server, могут оптимизировать
LEFT JOIN
/IS NULL
, чтобы вернутьFALSE
, как только найденное совпадение будет найдено, и это только для системы, которая хотела бы документировать это поведение. [& hellip;] Поскольку MySQL не способен использовать алгоритмы объединенияHASH
иMERGE
, единственнымANTI JOIN
, который он способен, являетсяNESTED LOOPS ANTI JOIN
[& hellip;]
По существу, [
NOT IN
] - это тот же самый план, который используетсяLEFT JOIN
/IS NULL
, несмотря на то, что эти планы выполняются разными ветвями кода, и они выглядят по-разному в результатыEXPLAIN
. На самом деле алгоритмы на самом деле одинаковы, и запросы завершаются в одно и то же время.
[& hellip;]
Трудно сказать точную причину [падения производительности при использовании
NOT EXISTS
], так как это падение является линейным и, похоже, не зависит от распределения данных, количества значений в обеих таблицах и т.д., пока оба поля индексируются. Поскольку в MySQL есть три части кода, которые очень важны для выполнения одной задачи, возможно, что код, ответственный заEXISTS
, делает какую-то дополнительную проверку, которая занимает дополнительное время.
[& hellip;]
MySQL может оптимизировать все три метода, чтобы сделать своего рода
NESTED LOOPS ANTI JOIN
. [& Hellip;] Однако эти три метода генерируют три разных плана, которые выполняются тремя разными фрагментами кода. Код, выполняющий предикатEXISTS
, на 30% менее эффективен [& hellip;]Вот почему лучший способ поиска отсутствующих значений в MySQL использует
LEFT JOIN
/IS NULL
илиNOT IN
, а неNOT EXISTS
.
(добавлены акценты)
К сожалению, похоже, что проблема использования MySql в предложении "NOT IN", при показе экрана показан вариант подзапроса, возвращающий неверные результаты:
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>
Будьте осторожны NOT IN
не является псевдонимом для <> ANY
, но для <> 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
cant 'заменить на
SELECT c FROM t1 WHERE c NOT IN (SELECT c FROM t2)
Вы должны использовать
SELECT c FROM t1 WHERE c <> ANY (SELECT c FROM t2)
SELECT * FROM пользователей, ГДЕ users.id НЕ ВХОДИТ (ВЫБЕРИТЕ ID ИЗ userDetail)