当表中没有行时,为什么 SUM() 返回 0?

And*_*ton 5 sql-server

多年来我一直在说,如果您将聚合值分配给一个变量,如果没有返回行,您需要处理该变量。IE:

DECLARE @MyVar INT

SELECT @MyVar = SUM(t.MyValue) FROM dbo.MyTable t WHERE /* clause */

IF @MyVar IS NULL
    SET @MyVar = 0
Run Code Online (Sandbox Code Playgroud)

然而,一位开发人员最近指出,他们不需要进行 @@ROWCOUNT 检查,因为 SUM 总是返回一个值(即使没有行)。经过进一步挖掘,我发现 SQL Server 似乎存在不一致的行为:

所以如果我运行:

DECLARE @MyTable TABLE(ID INT, MyValue INT)

/* you get a value of 0 back */
SELECT ISNULL(SUM(t.MyValue),0) FROM @MyTable t WHERE t.ID = 100
Run Code Online (Sandbox Code Playgroud)

我得到一个值为 0 的单行。

但是,如果我添加一个 GROUP BY 子句:

DECLARE @MyTable TABLE(ID INT, MyValue INT)

/* when you add on a GROUP BY, you no longer get a record back */
SELECT ISNULL(SUM(t.MyValue),0) FROM @MyTable t WHERE t.ID = 100 GROUP BY t.ID
Run Code Online (Sandbox Code Playgroud)

我没有得到任何行(这是我所期望的),我已经对 MS 文档进行了一些挖掘,但找不到关于这种行为差异的参考。谁能解释为什么会这样?这也是 SQL Server 工作方式的变化吗?

注意:我的测试是在 SQL Server 2008R2

** 编辑:回顾我过去发送的一些电子邮件并更正了我的支票,我一直在说如果值仍然为 NULL 处理它......(不处理行以及分配的 NULL)

ype*_*eᵀᴹ 6

结果是正确的,即根据标准,据我所知。

相关问题:此查询的正确结果是什么?包含解释它的段落:

以下摘自总则7.9(GROUP BY条款的定义)

1) 如果没有<where clause>指定,那么让T是前面的结果<from clause>;否则, letT是前面的结果<where clause>

2) 案例:

a) 如果没有分组列,则结果<group by clause>是分组表T作为其唯一的组组成。

所以,当没有GROUP BY- 或者当我们有GROUP BY ()- 结果应该是一个单一的组。表是否为空都没有关系。您将在结果中得到一行*
如果表是空的(并且使用了该SUM()函数),您将获得一个带有NULLas 值的行- 您可以将其转换为0using ISNULL()

当您有 时GROUP BY t.id,每组将有一行。但是在您的情况下有 0 个组,因此结果中有 0 行。

* :SQL-Server 将返回 0 行用于查询GROUP BY (),这与标准相矛盾。

  • @Andrew 不是真的。[2000 RTM 和 2005 RTM 都返回 0,而不是空集](http://i.stack.imgur.com/E4LeK.png),给出了问题中的样本。 (3认同)