【问题标题】:Need help with correct SQL需要有关正确 SQL 的帮助
【发布时间】:2010-06-30 23:16:22
【问题描述】:

所以我是一个菜鸟,初学者,初学者 - 把上面所有的东西都扔给我。我正在尝试创建一个查询,该查询将搜索数据库并返回等等等等。问题是,它不是很有效。这是一个示例查询 - 正如您所看到的,在其他事情之上,我试图返回姓氏为 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 

这将返回 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 BookingInfo.BookingDate = '05-18-2010' AND BookingInfo.ClinicID = '1' 
  OR BookingInfo.ClinicID = '2' 
ORDER BY BookingInfo.BookingDate DESC 

这会返回我指定日期的结果,但也返回其他日期。我的语法有问题吗?我不知道我在做什么吗?请帮助初学者。谢谢!

【问题讨论】:

  • AND 和 OR 变得混乱。将两个 OR 条件放在一组括号中并尝试。

标签: mysql


【解决方案1】:

查看 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 具有更高的优先级吗?

是的,我确定 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 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')

【讨论】:

  • 您确定AND 具有更高的优先级吗?我在 sqlzoo.net/3b.htm 这个页面上对其进行了测试,在我看来,这些语句是从左到右执行的,具有相同的优先级(当然不包括括号)。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • Randolph -- 如果你想复制这个答案,我会删除我的。
    • 保留积分。我没有耐心把它全部写出来:-)
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-22
        • 2017-08-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多