我有这个问题:
SELECT * FROM (`users`) WHERE `date_next_payment` <= '2011-02-02'
AND `status` = 'active' OR `status` = 'past due'
哪个不能返回正确的结果。但是,在OR条件周围添加括号使其工作如下:
SELECT * FROM (`users`) WHERE `date_next_payment` <= '2011-02-02'
AND (`status` = 'active' OR `status` = 'past due')
我的问题是为什么它有所不同?据我所知,在没有括号的情况下,OR语句会有所不同;但我不明白它是如何不同的。
我没有找到任何对此有帮助的文档。如果那里有任何链接,我真的很感激。
答案 0 :(得分:24)
这是因为OR比AND低operator precedence。每当数据库看到类似
的表达式时A AND B OR C
首先评估AND,即它等同于
(A AND B) OR C
所以如果你明确想要
A AND (B OR C)
相反,你必须放入括号。
这不是特定于SQL的。这些运算符的优先顺序在我所知的所有编程语言中都是相同的(即至少是C,C ++,C#,Java和Unix shell脚本)。
答案 1 :(得分:5)
SELECT * FROM (`users`) WHERE `date_next_payment` <= '2011-02-02'
AND `status` = 'active' OR `status` = 'past due'
在此示例中,您将获得所有记录
a)date_next_payment在2011年2月2日之前且状态为活动
b)状态为past_due
所以past_due记录不受日期限制。
SELECT * FROM (`users`) WHERE `date_next_payment` <= '2011-02-02'
AND (`status` = 'active' OR `status` = 'past due')
在此示例中,您将获得所有记录
a)date_next_payment在2011年2月2日之前
和
b)状态为active或past_due
括号的工作方式与数学或逻辑中的一样 - 括号内的语句首先得到评估......所以想象看到每个步骤都是这样的:
SELECT * FROM (`users`) WHERE `date_next_payment` <= '2011-02-02'
AND (`status` = 'active' OR `status` = 'past due')
因此遇到状态为活动的记录......
SELECT * FROM (`users`) WHERE `date_next_payment` <= '2011-02-02'
AND (TRUE OR FALSE)
然后使用OR条件评估...(TRUE或FALSE)== TRUE
SELECT * FROM (`users`) WHERE `date_next_payment` <= '2011-02-02'
AND TRUE
日期是2011-01-01
SELECT * FROM (`users`) WHERE TRUE
AND TRUE
最后,TRUE AND TRUE == TRUE
SELECT * FROM (`users`) WHERE TRUE
所以记录被返回......
想象您的查询是按照这样的步骤对数据库中的每一行执行的,有时会有助于理解放置括号的位置。
答案 2 :(得分:2)
in
SELECT * FROM (`users`) WHERE `date_next_payment` <= '2011-02-02'
AND `status` = 'active' OR `status` = 'past due'
它将首先考虑date_next_payment <= '2011-02-02' AND status = 'active'
,然后对此进行布尔答案或与status = 'past due'
在
中SELECT * FROM (`users`) WHERE `date_next_payment` <= '2011-02-02'
AND (`status` = 'active' OR `status` = 'past due')
首先完成OR然后将完成...那就是这将给出不同的答案
答案 3 :(得分:2)
MySQL手册在operator precedence上有一个页面。它表明AND具有更高的优先级。因此p1 AND p2 OR p3
被解释为(p1 AND p2) OR p3
。真值表很容易让你相信这与p1 AND (p2 OR p3)
不同。
答案 4 :(得分:1)
关于SQL并不特别,它是关于布尔逻辑的。 您的第一个陈述是:
a AND b OR c
这意味着如果任何c为真,你就会获得该行。
在AND(b OR c)中
只能获得a为真且(b或c)为真的行。
答案 5 :(得分:1)
添加括号时,您正在更改条件。
在初始情况下,结果集包含满足条件的记录
`date_next_payment` <= '2011-02-02' AND `status` = 'active'
或条件
`status` = 'past due'.
添加括号后,结果集将包含满足条件的记录
`date_next_payment` <= '2011-02-02'
和任何条件
`status` = 'active'
或
`status` = 'past due'
答案 6 :(得分:0)
在您的第一个查询中
status
='有效'是条件为假,然后未评估下一个状态列条件(status
)
在您的第二个查询中
括号()具有高优先级
。所以(status
='有效'或status
='过期')条件首先进行评估。
答案 7 :(得分:0)
这是因为当你没有使用括号时,实际上是在说:
`date_next_payment` <= '2011-02-02' AND `status` = 'active'
OR
`status` = 'past due'.
这意味着当status` ='逾期'时,也会显示此记录。不顾其他条件。
但是当你使用括号时,你需要:
`date_next_payment` <= '2011-02-02'
并传递其他两个条件之一。