Кто-нибудь может объяснить, почему на земле эти запросы не совпадают? - PullRequest
2 голосов
/ 04 февраля 2010

У меня есть запрос, который выглядит следующим образом:

select field_1, field_2
from source_table
minus
select field_1, field_2
from source_table
where status_code in (3, 600);

Когда я посмотрел на этот запрос, я сразу подумал: «Это глупо. Почему бы просто не использовать« НЕ В »и удалить бизнес МИНУС?

select field_1, field_2
from source_table
where status_code not in (3, 600);

Просто чтобы перепроверить мое здравомыслие, я получил счетчик каждого запроса. К моему удивлению, первый запрос вернул 789 089 записей, а второй запрос - 1 518 450 записей!

Я смотрел на это с нескольких сторон, но не могу понять, насколько эти два запроса различны. Кто-нибудь может объяснить, что происходит, или почему я сегодня идиот?

Ответы [ 4 ]

9 голосов
/ 04 февраля 2010

Эти запросы действительно разные. field_1 и field2 не равняются status_code 3 и 600. field_1 может быть 'A', а field_2 может быть 'B', поэтому вы удалите записи из первого SELECT, которые выглядят как A, B. Оригинал, вероятно, лучший способ достижения правильного результата.

Изменить: Чтобы дать вам лучшее представление о том, что происходит, вы можете получить тот же результат, аналогично тому, как вы думали написать запрос, выполнив подзапрос:

select distinct field_1, field_2
from source_table
where (field_1, field_2) not in (
    select field_1, field_2
    from source_table
    where status_code in (3, 600)
);
4 голосов
/ 04 февраля 2010

Операторы UNION, MINUS и INTERSECT возвращают только уникальные значения. Если у вас есть две строки с одинаковыми field_1 и field_2, первый запрос посчитает их один раз, а второй посчитает дважды:

SQL> insert into source_table values ('a', 'b', 10);

SQL> insert into source_table values ('a', 'b', 10);

SQL> select field_1, field_2
  2  from source_table
  3  minus
  4  select field_1, field_2
  5  from source_table
  6  where status_code in (3, 600);

FIELD_1    FIELD_2
---------- ----------
a          b

SQL> select field_1, field_2
  2  from source_table
  3  where status_code not in (3, 600);

FIELD_1    FIELD_2
---------- ----------
a          b
a          b
4 голосов
/ 04 февраля 2010

Если нет уникального ограничения на комбинацию field_1 и field_2, второй запрос может содержать дубликаты, а первый не будет, так как «минус» будет их подавлять. Попробуйте второй запрос с «отчетливым» и посмотрите, совпадают ли значения.

3 голосов
/ 04 февраля 2010

Если у вас нет уникального ограничения на field_1, field_2 или оба, Элисон, вероятно, права. Считайте, что у вас есть таблица: A B 3 A B 10

Первый запрос исключит обе строки, а второй - только одну. Кроме того, если у вас есть NULL-значения в столбце status_code, вы можете получить другие результаты (A или не A) не работает в SQL, если у вас есть NULL-значения в столбцах.

...