与TOTAL()的SQLite查询返回空行,抛出ConstraintException上阅读
问题描述:
我有一个使用了TOTAL()
聚合函数的SQL查询:与TOTAL()的SQLite查询返回空行,抛出ConstraintException上阅读
SELECT
c.Id,
c.Name,
...
b.BatchNumber,
TOTAL(d.OrderedAmount) as TotalOrderedAmount
FROM OrderProducts a
LEFT JOIN WarehouseProducts b ON a.WarehouseProductId = b.Id
...
WHERE a.OrderId = @OrderId
AND (e.Status = @OrderedStatus OR e.Status IS NULL)
(多余的行为清楚起见移除)
这即使没有找到结果,查询也会返回至少一行,导致每列都是DBNull(我假设)。当我尝试将此查询的结果加载到DataTable中时,由于空值,我得到一个ConstraintException。
如果我用0 as TotalOrderedAmount
替换TOTAL()
行,返回的行数为0,一切正常。
我试过使用WHERE a.Id IS NOT NULL
,但无论我尝试,总是至少有一行返回。
如何修改此查询,以便在没有找到产品时返回的行数为0,即使使用聚合函数?
答
这就是SQL中的聚合查询的工作原理。 的SQLite documentation说一下:
如果SELECT语句没有GROUP汇总查询BY子句,然后在结果集中的每个集合表达式一旦整个数据集进行评估。结果集中的每个非集合表达式都会针对数据集的任意选定行进行一次评估。每个非聚合表达式都使用相同的任意选择的行。或者,如果数据集包含零行,则将针对完全由NULL值组成的行评估每个非聚合表达式。
通过评估结果集中的聚合和非聚合表达式创建的单行结果集数据形成不带GROUP BY子句的聚合查询的结果。没有GROUP BY子句的聚合查询总是只返回一行数据,即使输入数据为零行。
要允许空结果,必须从最外层的查询中删除聚合函数TOTAL
。 为了仍然得到这个值(如果有一个结果记录),使用子查询:
SELECT
c.Id,
c.Name,
...
b.BatchNumber,
(SELECT TOTAL(d.OrderedAmount)
FROM SomeTable d
WHERE d.x = c.y -- or however d is related to the other tables
) AS TotalOrderedAmount
FROM OrderProducts a
JOIN ... -- without d here
WHERE ...
可能的解决办法是在回答[这个问题](扩展方法http://stackoverflow.com/questions/ 7580929/mysqldatareader-datatable-fillreader-throws-constraintexception),这将允许您加载没有约束的DataTable。 – davmos 2013-05-04 22:49:32