需要有关正确SQL的帮助

时间:2010-06-30 23:16:22

标签: mysql

所以我是一个noobie,首发,初学者 - 把所有上述内容扔给我。我正在尝试创建一个将在数据库中搜索并返回等等等等的查询。问题是,它不是很有效。这是一个示例查询 - 正如您所看到的,在其他事情之上,我试图返回姓氏为Johnson的人的结果

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 个答案:

答案 0 :(得分:5)

查看AND和OR之间的优先顺序。

在算术中,乘法的优先级高于加法。

示例:10 + 10 * 10 = 110,但是(10 + 10)* 10 = 200。

与AND和OR类似。 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无法识别日期文字。您必须使用YYYY-MM-DD格式。这可能会导致另一个问题。

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

重新评论:

  

你确定AND的优先级更高吗?

是的,我确信并且优先级高于OR。首先,这里记录了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或FALSE替换每个比较:

TRUE AND FALSE OR TRUE
FALSE AND FALSE OR TRUE

如果OR具有更高的优先级,它将按如下方式进行评估:

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

由于任何值与OR TRUE结合产生TRUE,这些括号内的子表达式将减少为:

TRUE AND (TRUE)
FALSE AND (TRUE)

第二行不匹配,因为FALSE和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 :(得分:1)

这可能是因为你的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的答案,并帮助最终查看您的代码的任何其他人。

答案 2 :(得分:0)

应该归功于@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 

答案 3 :(得分:0)

您需要在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的每个行;不只是约翰逊的。

答案 4 :(得分:0)

如果你在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