Нужна помощь с правильным SQL - PullRequest
3 голосов
/ 01 июля 2010

Итак, я новичок, начинающий, начинающий - брось все вышеперечисленное в меня.Я пытаюсь создать запрос, который будет искать в базе данных и возвращать бла-бла-бла.Проблема в том, что это не совсем работает.Вот пример запроса - Как вы можете видеть, помимо прочего я пытаюсь вернуть результаты от кого-то с фамилией Джонсон

SELECT BookingInfo.ClinicID, BookingInfo.BookingDate, BookingInfo.BookingTime, 
  BookingInfo.Status, PatientBooking.FirstName, PatientBooking.LastName, 
  PatientBooking.DateOfBirth 
FROM BookingInfo LEFT JOIN PatientBooking 
  ON BookingInfo.PatientID = PatientBooking.PatientID 
WHERE PatientBooking.LastName = 'Johnson' AND BookingInfo.ClinicID = '1' 
  OR BookingInfo.ClinicID = '2' 
ORDER BY BookingInfo.BookingDate DESC 

. Это возвращает результаты и с Джонсоном, и с другими.Другое:

SELECT BookingInfo.ClinicID, BookingInfo.BookingDate, BookingInfo.BookingTime, 
  BookingInfo.Status, PatientBooking.FirstName, PatientBooking.LastName, 
  PatientBooking.DateOfBirth 
FROM BookingInfo LEFT JOIN PatientBooking 
  ON BookingInfo.PatientID = PatientBooking.PatientID 
WHERE BookingInfo.BookingDate = '05-18-2010' AND BookingInfo.ClinicID = '1' 
  OR BookingInfo.ClinicID = '2' 
ORDER BY BookingInfo.BookingDate DESC 

Возвращает результаты с указанной мной даты, но также и другие.Что-то не так с моим синтаксисом?Разве я понятия не имею, что я делаю?Пожалуйста, помогите новичку.Спасибо!

Ответы [ 5 ]

5 голосов
/ 01 июля 2010

Просмотрите порядок приоритета между AND и OR.

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

Пример: 10 + 10 * 10 = 110, но (10 + 10) * 10 = 200.

Это похоже на AND и OR.И имеет более высокий приоритет, чем ИЛИ, поэтому без скобок:

WHERE BookingInfo.BookingDate = '05-18-2010' AND BookingInfo.ClinicID = '1' 
  OR BookingInfo.ClinicID = '2'

работает так:

WHERE (BookingInfo.BookingDate = '05-18-2010' AND BookingInfo.ClinicID = '1') 
  OR BookingInfo.ClinicID = '2'

Но вы хотите, чтобы это работало так:

WHERE BookingInfo.BookingDate = '05-18-2010' AND 
  (BookingInfo.ClinicID = '1' OR BookingInfo.ClinicID = '2')

Поэтому вставьте скобки, чтобы убедиться, что порядок старшинства работает так, как вы хотите.


Я также только что заметил, что вы используете даты в формате MM-DD-YYYY, который не распознается.MySQL для литералов даты.Вы должны использовать формат ГГГГ-ММ-ДД.Это может вызывать другую проблему.

SELECT DATE('05-18-2010'); -- returns NULL
SELECT DATE('2010-05-18'); -- returns 2010-05-18

Ваш комментарий:

Вы уверены, что AND имеет более высокий приоритет?

Да, я уверен, И имеет более высокий приоритет, чем ИЛИ.С одной стороны, иерархия приоритета всех операторов в MySQL документирована здесь: http://dev.mysql.com/doc/refman/5.1/en/operator-precedence.html

Давайте рассмотрим пример, используя вашу первоначально заявленную проблему:

BookingDate   ClinicID 
2010-05-18    2
2008-05-18    2

WHERE BookingInfo.BookingDate = '2010-05-18' AND 
  BookingInfo.ClinicID = '1' OR BookingInfo.ClinicID = '2'

Используя это выражение,только первый ряд должен совпадать.Но вы обнаружили, что обе строки совпадают, хотя дата второй строки не верна.Зачем?Давайте заменим каждое сравнение либо на ИСТИНА, либо на ЛОЖЬ:

TRUE AND FALSE OR TRUE
FALSE AND FALSE OR TRUE

Если бы ИЛИ имел более высокий приоритет, он оценился бы так:

TRUE AND (FALSE OR TRUE)
FALSE AND (FALSE OR TRUE)

Поскольку любое значение в сочетании с ИЛИ ИСТИНА дает ИСТИНА,подвыражение в этих скобках будет уменьшено до:

TRUE AND (TRUE)
FALSE AND (TRUE)

И вторая строка не будет соответствовать, потому что FALSE AND TRUE приводит к FALSE.Но этого не может быть, поскольку вы обнаружили, что вторая строка неверно совпадает.

Фактически, AND имеет более высокий приоритет, чем OR, поэтому он действительно оценивает, как если бы у вас были круглые скобки вокруг подвыражения AND:

(TRUE AND FALSE) OR TRUE
(FALSE AND FALSE) OR TRUE

Что уменьшает до:

(FALSE) OR TRUE
(FALSE) OR TRUE

В обоих случаях FALSE OR TRUE выдает TRUE, и обе строки совпадают.

Таким образом, без скобок семантика по умолчанию состоит в том, что AND имеетболее высокий приоритет, чем OR.Вам нужны скобки:

WHERE BookingInfo.BookingDate = '2010-05-18' AND 
  (BookingInfo.ClinicID = '1' OR BookingInfo.ClinicID = '2')
1 голос
/ 01 июля 2010

Это, вероятно, потому что у вас нет круглых скобок вокруг вашего условия OR.Попробуйте обновленную версию ниже:

SELECT BookingInfo.ClinicID, 
       BookingInfo.BookingDate, 
       BookingInfo.BookingTime,
       BookingInfo.Status, 
       PatientBooking.FirstName, 
       PatientBooking.LastName, 
       PatientBooking.DateOfBirth 
FROM       BookingInfo 
LEFT JOIN  PatientBooking 
ON         BookingInfo.PatientID = PatientBooking.PatientID 
WHERE      PatientBooking.LastName = 'Johnson' 
AND        BookingInfo.ClinicID IN ('1', '2') 
ORDER BY   BookingInfo.BookingDate DESC 

Кроме того, добавление небольшого форматирования в ваш SQL сделает его более читабельным.Это поможет вам получить ответы на вопросы о SO, а также поможет всем, кто в конечном итоге изучит ваш код.

0 голосов
/ 01 июля 2010

Если вы поставите скобки вокруг 2 условий ClinicID, это должно сработать.

См. Ниже:

SELECT BookingInfo.ClinicID, BookingInfo.BookingDate, BookingInfo.BookingTime, BookingInfo.Status, PatientBooking.FirstName, PatientBooking.LastName, PatientBooking.DateOfBirth FROM BookingInfo LEFT JOIN PatientBooking ON BookingInfo.PatientID = PatientBooking.PatientID WHERE PatientBooking.LastName = 'Johnson' AND (BookingInfo.ClinicID = '1' OR BookingInfo.ClinicID = '2') ORDER BY BookingInfo.BookingDate DESC 

SELECT BookingInfo.ClinicID, BookingInfo.BookingDate, BookingInfo.BookingTime, BookingInfo.Status, PatientBooking.FirstName, PatientBooking.LastName, PatientBooking.DateOfBirth FROM BookingInfo LEFT JOIN PatientBooking ON BookingInfo.PatientID = PatientBooking.PatientID WHERE BookingInfo.BookingDate = '05-18-2010' AND (BookingInfo.ClinicID = '1' OR BookingInfo.ClinicID = '2') ORDER BY BookingInfo.BookingDate DESC 
0 голосов
/ 01 июля 2010

Вам необходимо добавить круглые скобки вокруг части предложения WHERE, которая стоит перед OR. В первом примере то, что вы имеете в виду , равно

SELECT
    BookingInfo.ClinicID,
    BookingInfo.BookingDate,
    BookingInfo.BookingTime,
    BookingInfo.Status,
    PatientBooking.FirstName,
    PatientBooking.LastName,
    PatientBooking.DateOfBirth
FROM
    BookingInfo
    LEFT JOIN PatientBooking ON BookingInfo.PatientID = PatientBooking.PatientID
WHERE
    PatientBooking.LastName = 'Johnson' AND
    ( BookingInfo.ClinicID = '1' OR
      BookingInfo.ClinicID = '2'
      )
ORDER BY
    BookingInfo.BookingDate DESC

но поскольку AND имеет более высокий приоритет, чем OR, то, что вы на самом деле делаете , составляет

SELECT
    BookingInfo.ClinicID,
    BookingInfo.BookingDate,
    BookingInfo.BookingTime,
    BookingInfo.Status,
    PatientBooking.FirstName,
    PatientBooking.LastName,
    PatientBooking.DateOfBirth
FROM
    BookingInfo
    LEFT JOIN PatientBooking ON BookingInfo.PatientID = PatientBooking.PatientID
WHERE
    ( PatientBooking.LastName = 'Johnson' AND
      BookingInfo.ClinicID = '1'
      ) OR
    BookingInfo.ClinicID = '2'
ORDER BY
    BookingInfo.BookingDate DESC

Таким образом, вы увидите каждую строку, в которой ClinicID равно 2; не только Джонсона.

0 голосов
/ 01 июля 2010

Кредит должен идти к @Randolph Potter:

SELECT BookingInfo.ClinicID, BookingInfo.BookingDate, BookingInfo.BookingTime, BookingInfo.Status, PatientBooking.FirstName, PatientBooking.LastName, PatientBooking.DateOfBirth 
FROM BookingInfo 
    LEFT JOIN PatientBooking ON BookingInfo.PatientID = PatientBooking.PatientID 
WHERE 
    BookingInfo.BookingDate = '05-18-2010' AND 
    ( BookingInfo.ClinicID = '1' OR BookingInfo.ClinicID = '2' ) 
ORDER BY BookingInfo.BookingDate DESC 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...