Почему оператор OR дает мне записи, которые мне не нужны? - PullRequest
1 голос
/ 08 февраля 2012

Этот запрос:

select dept, job
from organizations
where (dept = 'Marketing' and job <> 'Sam Wise')
or    (dept = 'Marketing' and job <> 'The Precious')

Продолжает давать записи, в которых есть задания, показывающие «Драгоценный», когда это не должно.Но если я напишу запрос так:

select dept, job
from organizations
where (dept = 'Marketing' and job <> 'Sam Wise')
and   (dept = 'Marketing' and job <> 'The Precious')

Тогда я получу правильные записи.Нет работы, как «Сэм Мудрый» или «Драгоценный».Поэтому мне интересно, если мое понимание AND и OR в T-SQL сбито с толку или что-то не так с моим сервером sql.

Короче говоря, почему не первый запрос, удаляющий все записи с именем 'SamМудрый »или« Драгоценный »как работа, но второй запрос?

Ответы [ 7 ]

14 голосов
/ 08 февраля 2012

Это связано с тем, что если любое из ваших предложений OR в скобках окажется истинным, строка включается. Два ваших условия ИЛИ вместе взятые логически означают объединение всех рядов, где задание НЕ является «Сэмом Мудрым» или НЕ «Драгоценным». И все ряды соответствуют этим критериям, поскольку, например, «Сэм Мудрый» не является «Драгоценным» и поэтому отвечает второму условию.

Вот то, что я думаю, вы пытались:

select dept, job
from organizations
where
   dept = 'Marketing'
   and not (
      job = 'Sam Wise'
      or job = 'The Precious'
   )

И обратите внимание, вы можете просто использовать AND:

select dept, job
from organizations
where
   dept = 'Marketing'
   and job <> 'Sam Wise'
   and job <> 'The Precious'

Это хороший пример закона логики. Чтобы обозначить то же условие (A = X OR B = Y), но выразить его отрицательно (вы хотите, чтобы НЕ было впереди), оно всегда преобразуется в NOT (A <> X AND B <> Y). Он работает так же с (A = X AND B = Y) => NOT (A <> X OR B <> Y). В вашем случае A и B одинаковы, поэтому ваши условия запроса на job эквивалентны NOT (A = X AND A = Y), что, как полагают некоторые, всегда будет возвращать true, поскольку A = X AND A = Y никогда не может быть истинным.

Поскольку IN () может использоваться для выражения многих условий OR вместе, вы можете упростить запрос следующим образом: (хотя не работа, которую должен делать движок, это идентично).

select dept, job
from organizations
where
   dept = 'Marketing'
   and job not in ('Sam Wise', 'The Precious')

Чуть позже я понял, что перевод A = X => A <> X - это просто отрицание, в особом смысле этого слова. В простейшей форме закон логики выглядит следующим образом, учитывая два предложения P1 и P2:

  • NOT (P1 AND P2) => (NOT P1 OR NOT P2)
  • NOT (P1 OR P2) => (NOT P1 AND NOT P2)

Обратите внимание, что они тоже верны:

  • (P1 AND P2) => NOT (NOT P1 OR NOT P2)
  • (P1 OR P2) => NOT (NOT P1 AND NOT P2)

Это преобразования, которые также могут быть очень полезны.

9 голосов
/ 08 февраля 2012

Эти два пункта рассматриваются независимо. Может быть, попробуйте:

WHERE dept = 'Marketing' AND job NOT IN ('Sam Wise', 'The Precious');
4 голосов
/ 08 февраля 2012

Это просто, как работает ИЛИ, он вернет истину, если хотя бы одна часть верна.Давайте посмотрим, как будет работать первый запрос для строки, где Job == 'Sam Wise'.

(dept = 'Marketing' and 'Sam Wise' <> 'Sam Wise') -- FALSE
OR    
(dept = 'Marketing' and 'Sam Wise' <> 'The Precious') -- TRUE

Мы получили FALSE OR TRUE, поэтому весь WHERE возвращает TRUE.AND возвращает TRUE, если обе части TRUE, поэтому второй запрос возвращает ожидаемые результаты.

3 голосов
/ 08 февраля 2012

Допустим, у вас есть запись, которая является работой Сэма Уайза для отдела маркетинга.

Это оценивает таким образом:

(dept = 'Marketing' and job <> 'Sam Wise') 
OR (dept = 'Marketing' and job <> 'The Precious')

(TRUE and FALSE) 
OR (TRUE and TRUE)

(FALSE)
OR (TRUE)

(TRUE)

Так что этот документ включен. То же самое, если это Драгоценный. Ваш первый запрос по сути просто гарантирует, что он предназначен для отдела маркетинга.

3 голосов
/ 08 февраля 2012

Первая группа правил соответствует «Драгоценному», а вторая группа правил соответствует «Сэму Мудрому»

Другими словами, dept = 'Marketing' AND job <> 'Sam Wise' верно для строк, где dept = 'Marketing' and job = 'The Precious', поэтому эта строка выбрана. Аналогично, dept = 'Marketing' AND job <> 'The Precious' верно для строк, где dept = 'Marketing' and job = 'Sam Wise', поэтому эта строка также выбрана.

Лучший запрос будет таким:

SELECT dept, job
FROM organizations
WHERE
   dept = 'Marketing'
   and job <> 'Sam Wise'
   and job <> 'The Precious'
2 голосов
/ 08 февраля 2012

Часть оператора select:

where (dept = 'Marketing' and job <> 'Sam Wise')
or    (dept = 'Marketing' and job <> 'The Precious')

означает, что он будет возвращать запросы, если один или другой имеет значение true, или оба.Вот почему вы получаете нежелательные результаты.

statement1 = true OR statemet2 = true ...result true
statement1 = false OR statemet2 = true ...result true
statement1 = true OR statemet2 = false...result true
statement1 = false OR statemet2 = false ...result false

Использование AND, однако, вернет true только тогда, когда оба утверждения верны:

statement1 = true AND statemet2 = true ...result true
statement1 = false AND statemet2 = true ...result false
statement1 = true AND statemet2 = false...result false
statement1 = false AND statemet2 = false ...result false
1 голос
/ 08 февраля 2012

Эта концепция относится к математике и логике и не является строго кодирующей вещью. Это просто способ И и ИЛИ работать в логических терминах.

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