У вас две проблемы
1) Неправильный диагноз
Приведены две таблицы
mysql> CREATE TABLE T1 (ID INT);
Query OK, 0 rows affected (0.10 sec)
mysql> CREATE TABLE T2 (ID INT);
Query OK, 0 rows affected (0.10 sec)
mysql> INSERT INTO T1 VALUES (1);
Query OK, 1 row affected (0.00 sec)
в запросе
mysql> SELECT * FROM T1 LEFT OUTER JOIN T2 ON T1.ID != T2.ID;
+------+------+
| ID | ID |
+------+------+
| 1 | NULL |
+------+------+
1 row in set (0.00 sec)
возвращает несопоставленные строки, даже если T2 пуст (поэтому ваша проблема на самом деле в другом месте; вы, вероятно, упростили для нас запрос здесь).
2) Производительность запроса
Существует несколько способов написания запроса, который получает записи из таблицы A, отсутствующей в таблице B.
Однако они не все эквивалентны, например, mysql создает разные планы для
mysql> EXPLAIN SELECT * FROM T1 LEFT OUTER JOIN T2 ON T1.ID != T2.ID;
+----+-------------+-------+--------+---------------+------+---------+------+------+---------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+------+---------+------+------+---------------------+
| 1 | SIMPLE | T1 | system | NULL | NULL | NULL | NULL | 1 | |
| 1 | SIMPLE | T2 | system | NULL | NULL | NULL | NULL | 0 | const row not found |
+----+-------------+-------+--------+---------------+------+---------+------+------+---------------------+
2 rows in set (0.00 sec)
mysql> EXPLAIN SELECT * FROM T1 WHERE ID NOT IN (SELECT ID FROM T2);
+----+--------------------+-------+--------+---------------+------+---------+------+------+--------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+--------+---------------+------+---------+------+------+--------------------------------+
| 1 | PRIMARY | T1 | system | NULL | NULL | NULL | NULL | 1 | |
| 2 | DEPENDENT SUBQUERY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | no matching row in const table |
+----+--------------------+-------+--------+---------------+------+---------+------+------+--------------------------------+
2 rows in set (0.02 sec)
mysql> EXPLAIN SELECT * FROM T1 LEFT OUTER JOIN T2 ON T1.ID = T2.ID WHERE T2.ID IS NULL;
+----+-------------+-------+--------+---------------+------+---------+------+------+---------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+------+---------+------+------+---------------------+
| 1 | SIMPLE | T1 | system | NULL | NULL | NULL | NULL | 1 | |
| 1 | SIMPLE | T2 | system | NULL | NULL | NULL | NULL | 0 | const row not found |
+----+-------------+-------+--------+---------------+------+---------+------+------+---------------------+
2 rows in set (0.00 sec)
mysql> EXPLAIN SELECT * FROM T1 WHERE NOT EXISTS (SELECT ID FROM T2 WHERE T2.ID = T1.ID);
+----+--------------------+-------+--------+---------------+------+---------+------+------+--------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+--------+---------------+------+---------+------+------+--------------------------------+
| 1 | PRIMARY | T1 | system | NULL | NULL | NULL | NULL | 1 | |
| 2 | DEPENDENT SUBQUERY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | no matching row in const table |
+----+--------------------+-------+--------+---------------+------+---------+------+------+--------------------------------+
2 rows in set (0.00 sec)
Итак, для 4 разных версий одного и того же запроса (все они должны быть эквивалентны, если я не делал глупых ошибок) вы получаете два разных плана выполнения.
Оценка планов из этого примера должна не должно быть сделано, поскольку таблицы T1 и T2 содержат только одну и ноль строк соответственно, а планы do зависят от размера, индексов и статистики.Для производственных систем сравнивайте планы, так как я не думаю, что mysql распознает равенство этих запросов.
EDIT ИБП, я действительно совершил ошибку глупо интерпретация вашего запроса ...
SELECT * FROM T1 LEFT OUTER JOIN T2 ON T1.t_id != T2.t_id
Факты 1) При левом соединении
SELECT * FROM T1 LEFT OUTER JOIN T2 ...
будут получены все записи из T1 независимо от критериев соединения, если нет дополнительных условий WHERE (независимо от условия соединения!)
2) условие соединения определяет, какие записи будут объединяться с записями из T1 (определяет количество элементов и значения атрибутов из T2)
, поэтому дляДля конкретной записи из T1 она будет
2a) заполнять атрибуты из T2 NULLS только тогда и только тогда, когда условие соединения T1.t_id != T2.t_id
равно FALSE для ALL записейиз Т2.Это происходит только в том случае, если для конкретной записи в T1 каждая запись в T2 имеет то же значение t_id
, что и запись в T1.
2b), она возвратит ALL записей из T2, еслиусловие соединения - ИСТИНА, и все это определенно не то, что вам нужно
Вот пример продолжения ваших выборочных данных
mysql> INSERT INTO `T2` (`id`, `title`, `t_id`) VALUES (8, 'xdad', 3);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM T1 LEFT OUTER JOIN T2 ON T1.ID != T2.ID;
+----+--------+------+------+-------+------+
| id | title | t_id | id | title | t_id |
+----+--------+------+------+-------+------+
| 1 | apple | 1 | 8 | xdad | 3 |
| 2 | orange | 2 | 1 | dad | 2 |
| 2 | orange | 2 | 8 | xdad | 3 |
+----+--------+------+------+-------+------+
3 rows in set (0.00 sec)
Остальные три версии действительно должны быть эквивалентны
SELECT * FROM T1 LEFT OUTER JOIN T2 ON T1.t_id = T2.t_id WHERE T2.t_id IS NULL;
SELECT * FROM T1 WHERE NOT EXISTS (SELECT t_id FROM T2 WHERE T2.t_id = T1.t_id);
SELECT * FROM T1 WHERE t_id NOT IN (SELECT t_id FROM T2);
Последняя версия также может быть записана как
SELECT * FROM T1 WHERE t_id NOT IN (SELECT t_id FROM T2 WHERE T2.t_id = T1.t_id);
Извините за децентрацию с первой попытки ..