Venho dizendo há anos que, se você está atribuindo um valor agregado a uma variável, precisa lidar se não houver linhas retornadas. ou seja:
DECLARE @MyVar INT
SELECT @MyVar = SUM(t.MyValue) FROM dbo.MyTable t WHERE /* clause */
IF @MyVar IS NULL
SET @MyVar = 0
No entanto, um desenvolvedor apontou recentemente que não precisa fazer a verificação @@ROWCOUNT, pois SUM sempre retorna um valor (mesmo que não haja linhas). Ao fazer mais pesquisas, descobri que parece haver um comportamento inconsistente do SQL Server:
Então, se eu executar:
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
Eu recebo uma única linha com um valor de 0 de volta.
No entanto, se eu adicionar uma cláusula 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
Não recebo nenhuma linha de volta (que é o que eu esperava), fiz algumas pesquisas na documentação do MS, mas não consigo encontrar nenhuma referência a essa diferença de comportamento. Alguém pode explicar por que isso está ocorrendo? Além disso, isso é uma mudança na forma como o SQL Server funciona?
Obs: Meus testes foram no SQL Server 2008R2
** Editar: olhei para trás em alguns e-mails que enviei no passado e corrigi meu cheque, tenho dito Se o valor ainda for NULL, lide com isso ... (não lida com linhas e também com NULL atribuído)
O resultado está correto, ou seja, de acordo com os padrões, tanto quanto posso entender.
A pergunta relacionada: Qual é o resultado correto para esta consulta? contém o parágrafo que o explica:
Então, quando não há
GROUP BY
- ou quando temosGROUP BY ()
- o resultado deve ser um único grupo. Não importa se a mesa está vazia ou não. Você obterá uma única linha * no resultado.Se a tabela estiver vazia (e a
SUM()
função for usada), você obtém uma única linha comNULL
o valor - que você converte0
usandoISNULL()
.Quando você tiver
GROUP BY t.id
, terá uma linha para cada grupo. Mas existem 0 grupos no seu caso, então 0 linhas no resultado.* : o SQL-Server, no entanto, retornará 0 linhas para a consulta com
GROUP BY ()
, o que contradiz o padrão.