为什么我需要使用子查询来过滤分组选择?

Nat*_*ate 4 sql-server-2008 sql-server t-sql subquery

如果我这样做——

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
Run Code Online (Sandbox Code Playgroud)

我收到这个错误——

消息 207,级别 16,状态 1,第 17 行 列名“DE”无效。

如果我这样做——

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'
Run Code Online (Sandbox Code Playgroud)

它按预期工作。

有人可以解释为什么我需要将主查询嵌套为子查询来限制我的数据集吗?

另外,这里是否有更好的方法来实现目标?从一张表中检索所有记录,以及按[DateEntered]降序排列的单个“顶部”相关记录?

Aar*_*and 6

您不能在WHERE子句中引用别名- 这只是因为 SQL Server 分析语句的顺序。

在这里和 StackOverflow 上有很多关于这个的讨论。提供一些背景的几个例子:

https://dba.stackexchange.com/questions/19762/why-is-the-select-clause-listed-first/

为什么以不允许在大多数子句中使用列别名的方式解析查询?

另一种选择是:

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
HAVING MAX(hb.[DateEntered]) < '20130304';
Run Code Online (Sandbox Code Playgroud)