Оба реализуют те же интерфейсы, таким образом, они будут вести себя тот же путь. Возможно, они реализованы по-другому внутренне, но это должно было бы быть протестировано.
единственными реальными различиями, которые я вижу, являются пространства имен и то, которое Collection<T>
отмечено с ComVisibleAttribute(false)
, таким образом, код COM не может использовать его.
Обновление:
Эти статьи в моем блоге более подробно описывают различия между методами:
НЕ В
vs. НЕ СУЩЕСТВУЕТ
vs. LEFT JOIN / IS NULL
: SQL Server
NOT IN
vs. NOT EXISTS
vs. LEFT JOIN / IS NULL
: PostgreSQL
НЕ В
vs. НЕ СУЩЕСТВУЕТ
vs. LEFT JOIN / IS NULL
: Oracle
НЕ В
vs. НЕ СУЩЕСТВУЕТ
vs. LEFT JOIN / IS NULL
: MySQL
Есть три способа выполнить такой запрос:
LEFT JOIN / IS NULL
:
ВЫБРАТЬ *
ИЗ общего
LEFT JOIN
table1 t1
ВКЛ t1.common_id = common.common_id
ГДЕ t1.common_id ЕСТЬ NULL
НЕ СУЩЕСТВУЕТ
:
ВЫБРАТЬ *
ИЗ общего
ГДЕ НЕ СУЩЕСТВУЕТ
(
ВЫБРАТЬ NULL
ИЗ table1 t1
ГДЕ t1.common_id = common.common_id
)
НЕ В
:
ВЫБРАТЬ *
ИЗ общего
ГДЕ common_id НЕ В
(
ВЫБЕРИТЕ common_id
ИЗ table1 t1
)
Когда table1.common_id
не допускает значения NULL, все эти запросы семантически одинаковы.
Когда он допускает значение NULL, NOT IN
отличается, поскольку IN
(и, следовательно, NOT IN
) возвращает NULL
, когда значение не соответствует ничему в списке, содержащем NULL
.
Это может быть сбивает с толку, но может стать более очевидным, если мы вспомним альтернативный синтаксис для этого:
common_id = ANY
(
SELECT common_id
FROM table1 t1
)
Результатом этого условия является логическое произведение всех сравнений в списке. Конечно, одно значение NULL
дает результат NULL
, который также отображает весь результат NULL
.
Мы никогда не можем точно сказать, что common_id
не соответствует чему-либо из этого списка, поскольку по крайней мере одно из значений NULL
.
Предположим, у нас есть следующие данные:
common
--
1
3
table1
--
NULL
1
2
LEFT JOIN / IS NULL
и NOT EXISTS
вернет 3
, NOT IN
вернет ничего (так как всегда будет оцениваться как FALSE
или NULL
).
В MySQL
в случае столбца, не допускающего значения NULL, LEFT JOIN / IS NULL
и NOT IN
немного (на несколько процентов) более эффективны, чем НЕ СУЩЕСТВУЕТ
. Если столбец допускает значение NULL, NOT EXISTS
является наиболее эффективным (опять же, не очень).
В Oracle
все три запроса дают одинаковые планы ( ANTI JOIN
).
В SQL Server
,
Если вы хотите, чтобы мир был двузначным логическим местом, вы должны сами предотвратить случай null (третье значение).
Не пишите предложения IN, которые разрешают нули в сторона списка. Отфильтруйте их!
common_id not in
(
select common_id from Table1
where common_id is not null
)
SELECT T.common_id
FROM Common T
LEFT JOIN Table1 T1 ON T.common_id = T1.common_id
LEFT JOIN Table2 T2 ON T.common_id = T2.common_id
WHERE T1.common_id IS NULL
AND T2.common_id IS NULL
Таблица1 или Таблица2 имеет несколько нулевых значений для common_id. Вместо этого используйте этот запрос:
select *
from Common
where common_id not in (select common_id from Table1 where common_id is not null)
and common_id not in (select common_id from Table2 where common_id is not null)
select *
from Common c
where not exists (select t1.commonid from table1 t1 where t1.commonid = c.commonid)
and not exists (select t2.commonid from table2 t2 where t2.commonid = c.commonid)
Просто в голове ...
select c.commonID, t1.commonID, t2.commonID
from Common c
left outer join Table1 t1 on t1.commonID = c.commonID
left outer join Table2 t2 on t2.commonID = c.commonID
where t1.commonID is null
and t2.commonID is null
Я провел несколько тестов, и вот мои результаты по ответу @ patmortech и комментариям @rexem.
Если либо Table1, либо Table2 не индексируется по commonID, вы получаете сканирование таблицы, но запрос @patmortech по-прежнему в два раза быстрее (для главной таблицы со 100K строками).
Если ни одна из них не проиндексирована по commonID, вы получаете два сканирования таблицы, и разница незначительна.
Если оба индексируются по commonID, запрос «не существует» выполняется в 1/3 времени.
Let's suppose these values for common_id:
Common - 1
Table1 - 2
Table2 - 3, null
We want the row in Common to return, because it doesn't exist in any of the other tables. However, the null throws in a monkey wrench.
With those values, the query is equivalent to:
select *
from Common
where 1 not in (2)
and 1 not in (3, null)
That is equivalent to:
select *
from Common
where not (1=2)
and not (1=3 or 1=null)
This is where the problem starts. When comparing with a null, the answer is unknown. So the query reduces to
select *
from Common
where not (false)
and not (false or unkown)
false or unknown is unknown:
select *
from Common
where true
and not (unknown)
true and not unkown is also unkown:
select *
from Common
where unknown
The where condition does not return records where the result is unkown, so we get no records back.
One way to deal with this is to use the exists operator rather than in. Exists never returns unkown because it operates on rows rather than columns. (A row either exists or it doesn't; none of this null ambiguity at the row level!)
select *
from Common
where not exists (select common_id from Table1 where common_id = Common.common_id)
and not exists (select common_id from Table2 where common_id = Common.common_id)