使用TOTAL()的SQLite查询返回空行,在读取时抛出ConstraintException

时间:2013-05-04 22:05:26

标签: c# sqlite null aggregate-functions

我有一个使用TOTAL()聚合函数的SQL查询:

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。

如果我用TOTAL()替换0 as TotalOrderedAmount行,则返回的行数为0,一切正常。

我尝试使用WHERE a.Id IS NOT NULL,但无论我尝试什么,似乎总有至少一行返回。

如何修改此查询,以便在找不到产品时,返回的行数为0,即使使用聚合函数?

1 个答案:

答案 0 :(得分:1)

这就是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 ...