SQL中NOT能否作用于OR运算符?两种查询方案正确性辨析
首先明确回答你的第一个问题:网站解决方案里NOT作用于OR是完全合规的。SQL中的NOT运算符可以对任意完整的布尔表达式取反,只要用括号把OR连接的条件整体括起来,作为NOT的操作数,这是符合SQL语法规范的写法,没有问题。
接下来咱们分析两个方案的正确性,先回到题目需求本身:
题目要求显示两类订单:
- 订单日期不为2012-09-10 且 销售员ID为5005及以下的订单;
- 采购金额为1000.00及以下的订单。
翻译成逻辑表达式就是:(条件A) OR (条件B),其中
- 条件A:
ord_date <> '2012-09-10' AND salesman_id <= 5005 - 条件B:
purch_amt <= 1000.00
你的解决方案分析
你的SQL直接对应了这个逻辑:
select * from orders where (ord_date <> '2012-09-10' and salesman_id <= '5005') or purch_amt <= '1000';
这里提个小细节:如果salesman_id是数值类型、purch_amt是浮点/数值类型,去掉单引号写成salesman_id <= 5005和purch_amt <= 1000.00会更规范,但大多数数据库会自动做类型转换,不影响结果正确性。这个语句完全匹配题目要求的两类订单,是正确的。
网站解决方案分析
网站给出的SQL是:
SELECT * FROM orders WHERE NOT ((ord_date ='2012-09-10'AND salesman_id > 5005) OR purch_amt > 1000.00);
咱们用德摩根定律把这个逻辑展开,就能看清它的实际含义:
- 根据
NOT (X OR Y) = NOT X AND NOT Y,原语句可以拆成:NOT (ord_date ='2012-09-10'AND salesman_id > 5005) AND NOT (purch_amt > 1000.00) - 再对第一部分用
NOT (X AND Y) = NOT X OR NOT Y,展开后得到:(ord_date <> '2012-09-10' OR salesman_id <= 5005) AND purch_amt <= 1000.00
这个逻辑和题目需求完全不同!它的意思是:采购金额必须<=1000,同时满足(日期不是2012-09-10 或者 销售员ID<=5005)。这会漏掉那些采购金额<=1000,但同时日期是2012-09-10且销售员ID>5005的订单——而根据题目要求,这类订单属于第二类,应该被选中。
举个实际例子:假设存在订单ord_no=70014, purch_amt=500, ord_date='2012-09-10', salesman_id=5006,你的语句会选中它(因为满足条件B),但网站的语句不会(因为ord_date='2012-09-10'AND salesman_id>5005为true,所以NOT(X)为false,整个条件false AND true结果为false)。
最终结论
- 网站的写法语法合规,但逻辑不符合题目需求;
- 你的解决方案完全正确,精准匹配了题目要求的两类订单。
内容的提问来源于stack exchange,提问作者Guissous Allaeddine

