Что не так с этим простым запросом, использующим NOT IN? - PullRequest
3 голосов
/ 03 декабря 2009

Схема:

radio_bin.id
radio.id
radio.radio_bin -> radio_bin.id

Запросы:

select *
    from radio_bin

72 строки.

select *
    from radio_bin
    where id in (select radio_bin from radio)

50 строк.

(И FWIW:)

select distinct radio_bin
    from radio

51 ряд, включая ноль.

Это все хорошо. Сейчас:

select *
    from radio_bin
    where id not in (select radio_bin from radio)

0 строк.

Почему? Разве я не должен получить 22 номера radio_bin.id, которые не имеют радио, указывающее на них?

Ответы [ 5 ]

6 голосов
/ 03 декабря 2009

Попробуйте, у вас есть нулевое значение, и нуль не равен ничему, даже не другому нулю

select *
    from radio_bin
    where id not in (select radio_bin from radio where radio_bin  is not null)

См. Также NOT IN и NULLS , где показано, как использовать LEFT JOIN или NOT EXISTS

2 голосов
/ 03 декабря 2009

Возможно ли, что radio_bin.id равно null?

Если это NOT IN, значение не оценивается как истинное .

Это потому, что x NOT IN y эквивалентно NOT (x IN y). Если x равно null, то (x IN y) вернет ноль, поскольку ничто не равно null, даже null.

2 голосов
/ 03 декабря 2009

изменение

in

до

Exists

Это работает?

См. Здесь объяснение

1 голос
/ 03 декабря 2009

Избегайте использования NOT IN, если вы планируете существенно увеличить этот запрос. Если вы говорите о небольшом приложении, это не должно быть проблемой, но если вы говорите о миллионах строк (даже потенциально), избегайте такого подхода!

Отрицательные операции, такие как <> или НЕ Как и очень трудно решить эффективно. Попробуй переписать их по-другому, если можете. если ты проверяют только на наличие, используют ЕСЛИ СУЩЕСТВУЕТ или ЕСЛИ НЕ СУЩЕСТВУЕТ построить вместо. Вы можете использовать индекс. Если вы используете сканирование, вы можете остановить сканирование при первом появлении. http://msdn.microsoft.com/en-us/library/ms998577.aspx

1 голос
/ 03 декабря 2009

Потому что NULL действительно все портят. Следующее было выполнено в Oracle, но я думаю, что это стандартное поведение ANSI SQL ...

SQL> select * from t23
  2  where id in ( select id from t42)
  3  /

TXT                                                ID
------------------------------------------ ----------
SAM-I-AM                                            1
KNOX                                                2
FOX                                                 3

SQL> select * from t23
  2  where id not in ( select id from t42)
  3  /

no rows selected

SQL> update t42 set id = 8 where id is null
  2  /

1 row updated.

SQL> select * from t23
  2  where id not in ( select id from t42)
  3  /

TXT                                                ID
------------------------------------------ ----------
LORAX                                               9

SQL>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...