使用WHERE
子句测试涉及除法的SQL查询时,我遇到了一个看似奇怪的错误。任务是在以下 any 为真的情况下查找发票中的错误:
Amount
或Tax
均为零(不是两个); Amount
和Tax
都不为零,但它们不满足某些算术条件。所以我想出的查询如下:
SELECT InvoiceNumber, InvoiceDate, Amount, Tax
FROM Invoices
WHERE (Amount <> 0 AND Tax = 0)
OR (Amount = 0 AND Tax <> 0)
OR (Amount <> 0 AND Tax <> 0 AND ABS(Tax / Amount - 0.18) > 0.005)
为了使事情更奇怪,此查询可以正常运行:
SELECT InvoiceNumber, InvoiceDate, Amount, Tax
FROM Invoices
WHERE Amount <> 0 AND Tax <> 0 AND ABS(Tax / Amount - 0.18) > 0.005
我猜想SQL Server条件子句中的布尔值评估不能像C#中那样工作(我可以期望懒惰的评估防止零错误除法)。
如何使该查询正确?
注意: :有数千万条记录,因此嵌套的SELECT
语句可能会影响性能。
答案 0 :(得分:3)
不要依赖于查询中子句或条件的求值顺序。期。 优化器保留重新安排所有内容以提高性能的权利。好的,不是全部。 CASE
表达式具有确定的求值顺序。
解决方案非常简单。使用NULLIF()
:
WHERE (Amount <> 0 AND Tax = 0) OR
(Amount = 0 AND Tax <> 0) OR
(Amount <> 0 AND Tax <> 0 AND ABS(Tax / NULLIF(Amount, 0) - 0.18) > 0.005)
WHERE Amount <> 0 AND Tax <> 0 AND ABS(Tax / NULLIF(Amount, 0) - 0.18) > 0.005
答案 1 :(得分:-1)
您尝试使用括号
SELECT InvoiceNumber, InvoiceDate, Amount, Tax
FROM Invoices
WHERE (Amount <> 0 AND Tax = 0)
OR (Amount = 0 AND Tax <> 0)
OR (Amount <> 0 AND Tax <> 0 AND ABS(Tax / Amount - 0.18) > 0.005)
在处理多个条件(或/和)时,请尝试使用“()”进行分隔。
运算符的逻辑顺序是
您可以使用括号来处理此规则。