Поведение нечетных скобок в предложении Where - PullRequest
1 голос
/ 25 марта 2020

НАСТРОЙКА:

MySQL 5.7.14 (Google SQL)

ОПИСАНИЕ:

In в следующем сценарии кажется, что я получаю несколько ложных совпадений в предложении where, где я НЕ использую скобки. Но добавление скобок даёт правильные результаты.

Этот запрос возвращает результаты с tsd.StatusID = 3 (неверно) :

SELECT 
tsee.ID, tsd.StatusID

FROM TSShiftDetails tsd
JOIN TSShiftEmployees tse
    ON tse.ShiftID = tsd.ID
JOIN TSShiftEmpEntries tsee
    ON tsee.ShiftEmpID = tse.ID

WHERE tsee.CCID IN (4590) OR tsee.CCID LIKE null
AND tsd.StatusID != 3

Хотя этот запрос ДЕЛАЕТ НЕ возвращает результаты с AND tsd.StatusID = 3 (правильно) :

SELECT 
tsee.ID, tsd.StatusID

FROM TSShiftDetails tsd
JOIN TSShiftEmployees tse
    ON tse.ShiftID = tsd.ID
JOIN TSShiftEmpEntries tsee
    ON tsee.ShiftEmpID = tse.ID

WHERE (tsee.CCID IN (4590) OR tsee.CCID LIKE null)
AND tsd.StatusID != 3

ВОПРОС:

Хотя я полностью понимаю, почему запрос с круглыми скобками работает. Мой вопрос: ПОЧЕМУ тот, кто без скобок возвращает записи с StatusID == 3? Я думаю, что без какого-либо функционального упорядочения скобок предложение AND tsd.StatusID != 3 будет применяться к каждому совпадению независимо от предшествующего OR.

Что я подумаю? Я неправильно понимаю, или MySQL ведет себя здесь непоследовательно?

PS

К вашему сведению, Да, существует причина применения внешнего интерфейса для необходимости иметь условие Where отформатирован таким образом. например. tsee.CCID IN (4590) в отличие от tsee.CCID =4590

1 Ответ

1 голос
/ 25 марта 2020

Объяснение не имеет ничего общего с LIKE NULL или IN ( ).

Булевы выражения следуют порядку приоритета оператора, так же как арифмети c.

В арифметике c, вы, возможно, помните, что умножение имеет более высокий приоритет, чем сложение:

A + B * C

Без скобок это работает точно так же:

A + (B * C)

Если вы хотите, чтобы сложение оценивалось первым, вы необходимо использовать скобки для переопределения приоритета оператора по умолчанию:

(A + B) * C

Аналогично, в логических выражениях AND имеет более высокий приоритет, чем OR.

A OR B AND C

Работает так:

A OR (B AND C)

Если вы хотите, чтобы OR оценивался первым, вы должны использовать скобки, чтобы переопределить приоритет оператора по умолчанию:

(A OR B) AND C

Как это объясняет то, что вы видите?

WHERE tsee.CCID IN (4590) OR tsee.CCID LIKE null
AND tsd.StatusID != 3

Это работает так, как если бы вы сделали:

WHERE tsee.CCID IN (4590) OR (tsee.CCID LIKE null
AND tsd.StatusID != 3)

Так что, если он находит строку с CCID 4590, эта строка удовлетворяет всему предложению WHERE, потому что true OR (anything) все еще верно .

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