Aqui temos duas consultas semelhantes usando grouping sets
onde a SELECT
cláusula contém algumas expressões calculadas em agregação:
SELECT RN10, RN10 / 10, COUNT(*) FROM
(
SELECT RN, RN/10 AS RN10, RN/100 AS RN100 FROM
(
SELECT RN = -1 + ROW_NUMBER() OVER (ORDER BY 1/0)
FROM master..spt_values
) A
) B
GROUP BY GROUPING SETS ((RN10), (RN10 / 10), ())
ORDER BY 1, 2
seu plano está aqui: primeiro plano de consulta
e
SELECT RN10, SUBSTRING(RN,3,99), COUNT(*) FROM
(
SELECT RN, SUBSTRING(RN,2,99) AS RN10 FROM
(
SELECT RN = CAST(-1 + ROW_NUMBER() OVER (ORDER BY 1/0) AS VARCHAR(99))
FROM master..spt_values
) A
) B
GROUP BY GROUPING SETS ((RN10), (SUBSTRING(RN,3,99)), ())
ORDER BY 1, 2
o plano correspondente está aqui: segundo plano de consulta
Ambas as consultas primeiro calculam alguma expressão para agregação, RN10 / 10
no primeiro caso e SUBSTRING(RN,3,99)
no segundo, então a mesma expressão é usada na SELECT
cláusula, mas como o primeiro plano mostra ela é recalculada na primeira consulta e não na segunda.
Como resultado, temos NULL
s no primeiro conjunto de resultados que é bastante inesperado:
Alguém pode explicar porque a primeira consulta faz o cálculo 2 vezes (uma na agregação e mais uma vez na final select
) enquanto a segunda faz apenas uma vez?
Vou usar um exemplo mais simples onde fica claro para ver quais são os resultados esperados.
Consulta 1
Resultados da Consulta 1
Consulta 2
Resultados da Consulta 2
Apesar do
ORDER BY SurnameInitial
fato deNULL
classificar primeiro no SQL Server as linhas comSurnameInitial
asNULL
são ordenadas por último.As consultas 1 e 2 devem retornar os mesmos resultados. O problema é que o SQL Server decide tratá-lo como o seguinte SQL
Isso só parece um bug para mim (o sinalizador de rastreamento 8605 mostra que o dano já foi feito na representação inicial da árvore de consulta). RELATÓRIO DE ERRO .
Consulta 3
Resultados da Consulta 3
Query3 não atende ao padrão problemático de agrupamento em uma coluna e uma expressão que faz referência a essa coluna. De qualquer forma, nem seria possível que o mesmo problema ocorresse aqui porque a parte dos conjuntos de agrupamento é equivalente a
Isso não passa toda a coluna upstream (ou mesmo tem uma coluna
FirstName
exclusiva garantida que pode ser passada), então não é possível que a expressão seja calculada em cima disso.FirstName
LEFT(FirstName,1)
Pela mesma razão que você não vê o problema com
(RN10), (SUBSTRING(RN,3,99))
.@i-one raciocina nos comentários que é provável
sem ter que adicionar explicitamente a expressão calculada como abaixo
Ou outro exemplo seria
Neste caso, o
LEFT(Surname,2)
é permitido e a única maneira de calcular seria fazê-lo da maneira problemática para oLEFT(Surname,1)
caso.