【问题标题】:SQLite query with TOTAL() returns empty row, throws ConstraintException on read使用 TOTAL() 的 SQLite 查询返回空行,读取时抛出 ConstraintException
【发布时间】:2013-04-29 01:37:45
【问题描述】:

我有一个使用 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 中时,由于 null 值,我得到了一个 ConstraintException。

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

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

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

【问题讨论】:

  • 可能的解决方法是this question 答案中的扩展方法,它允许您在没有约束的情况下加载 DataTable。

标签: c# sqlite null aggregate-functions


【解决方案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 ...

【讨论】:

    猜你喜欢
    • 2011-06-28
    • 2014-09-17
    • 1970-01-01
    • 1970-01-01
    • 2011-11-26
    • 1970-01-01
    • 2016-06-04
    • 1970-01-01
    • 2017-11-30
    相关资源
    最近更新 更多