Se eu fizer isso -
SELECT dv.Name
,MAX(hb.[DateEntered]) as DE
FROM
[Devices] as dv
INNER JOIN
[Heartbeats] as hb ON hb.DeviceID = dv.ID
WHERE DE < '2013-03-04'
GROUP BY dv.Name
Eu recebo este erro -
Msg 207, Nível 16, Estado 1, Linha 17 Nome de coluna inválido 'DE'.
Se eu fizer isso -
SELECT Name, DE FROM (
SELECT dv.Name
,MAX(hb.[DateEntered]) as DE
FROM
[Devices] as dv
INNER JOIN
[Heartbeats] as hb ON hb.DeviceID = dv.ID
GROUP BY dv.Name
) as tmp WHERE tmp.DE < '2013-03-04'
funciona como esperado.
Alguém pode explicar por que preciso aninhar minha consulta principal como uma subconsulta para limitar meu conjunto de dados?
Além disso, talvez haja uma maneira melhor de atingir o objetivo aqui? Recuperar todos os registros de uma tabela e o único registro relacionado "top" ordenado por ordem [DateEntered]
decrescente?
Você não pode fazer referência a um alias na
WHERE
cláusula - isso ocorre apenas por causa da ordem na qual o SQL Server analisa a instrução.Houve muitas discussões sobre isso aqui e no StackOverflow. Alguns exemplos que fornecem algumas informações básicas:
https://dba.stackexchange.com/questions/19762/why-is-the-select-clause-listed-first/
Por que as consultas são analisadas de forma que não permite o uso de aliases de coluna na maioria das cláusulas?
Uma alternativa seria:
Há algumas coisas que são importantes aqui. Primeiro, há uma ordem lógica de processamento que ocorre. E a atribuição de seu
DE
alias de coluna naSELECT
cláusula ocorre após oWHERE
processamento da cláusula. Portanto, oDE
alias não é válido naWHERE
cláusula.Observe que a solução de subconsulta é processada logicamente antes da consulta externa, portanto, o
DE
alias é atribuído à coluna antes de você fazer referência a ela.Você pode alterar a consulta original para fazer o que quiser. Aqui está uma maneira.
Mova seu teste de data para a
HAVING
cláusula, onde você pode testar agregações. Isso excluirá os dados depois de terem sido agrupados. Esperançosamente, é isso que você está tentando fazer.