【发布时间】:2018-10-04 13:35:12
【问题描述】:
在使用涉及除法的WHERE 子句测试SQL 查询时,我遇到了一个看似奇怪的错误。任务是找出发票中任何以下情况为真的错误:
-
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 语句可能会影响性能。
【问题讨论】:
-
Amount <> 0.18? -
可能只是在表达式周围加上适当的括号,以确保您在判断运算符优先级时不会出错。
-
@Cid 不会先做除法吧,可能还需要
ABS(Tax / (Amount - 0.18))。 -
@SteveSmith 确实应该这样做,但谁知道优先级是否得到很好的尊重?
-
NULLIF(Amount, 0)。不允许除以 0,但除以NULL是允许的。正如您所发现的,强制优化器不计算表达式基本上是不可能的。即使CASE也并不总是有效。
标签: sql sql-server divide-by-zero