在where子句中使用ranking-function派生列(SQL Server 2008)

时间:2009-09-25 22:25:49

标签: sql sql-server sql-server-2008

希望这对于SQL-Ninja来说是微不足道的......试图让以下查询工作:

这适用于SQL Server 2008

SELECT 
    ROW_NUMBER() OVER (ORDER BY Date_Time DESC) AS RowNumber, *
FROM
    (SELECT 
         T.A_ID, T.User_Name, T.Date_Time, T.Value,
         U.ID, U.Name, U.Field1, U.Field2,
         COUNT(U.ID) OVER () AS TotalRows
     FROM 
        TeeTable as T 
    INNER JOIN 
        YouTable AS U ON T.U_ID = U.ID
    WHERE 
        T.Value BETWEEN 222 AND 225) Filtered
WHERE 
    RowNumber BETWEEN 1 AND 5

这些值在某种程度上是为了给出一个具体的例子而设计的,但是查询的精神被完全保留了下来。我从这句话得到的错误是:

  

无效的列名称'RowNumber'。

如果我删除最后的WHERE子句(RowNumber BETWEEN ...),它返回一个预期的结果集(A_ID,User_Name,Date_Time等...),在所述结果中RowNumber为一列(具有敏感值)。但我无法在WHERE子句中与它进行比较。我显然做了一些愚蠢的事情,但这达到了我的SQL限制!

我已经尝试将其重新安排为CTE(WITH FILED AS ......)但最终结果是相同的,看起来这只是我已经在做的糖。

想法?如何过滤RowNumber派生列?

3 个答案:

答案 0 :(得分:16)

您必须将WHERE运算符移动到项目列表上方,其中创建了RowNumber列。使用派生表或CTE:

SELECT * 
  FROM (
   SELECT *, ROW_NUMBER() OVER (...) as RowNumber
   FROM ...) As ...
 WHERE RowNumber = ...

等效的CTE是:

WITH cte AS (
SELECT *, ROW_NUMBER() OVER (...) as RowNumber
       FROM ...)
SELECT * FROM cte 
WHERE RowNumber = ...   

答案 1 :(得分:5)

在WHERE子句之后,在查询的最后阶段填充了窗口函数(其中ROW_NUMBER是最熟悉的)。因此,您也必须将其嵌套,以便对其进行过滤:

SELECT *
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY Date_Time DESC) AS RowNumber, *
    FROM
    ( SELECT T.A_ID, T.User_Name, T.Date_Time, T.Value,
             U.ID, U.Name, U.Field1, U.Field2,
             COUNT(U.ID) OVER () AS TotalRows
      FROM 
        TeeTable as T INNER JOIN YouTable AS U
        ON T.U_ID = U.ID
        WHERE T.Value BETWEEN 222 AND 225
    ) Numbered
)  Filtered
WHERE RowNumber BETWEEN 1 AND 5

您也可以将它们放在CTE或视图中以获得相同的效果。

答案 2 :(得分:0)

由于逻辑处理顺序中的错误,查询出现问题。这是MSDN开发网络中指定的逻辑处理顺序。

SELECT语句的逻辑处理顺序 以下步骤显示SELECT语句的逻辑处理顺序或绑定顺序。此顺序确定在一个步骤中定义的对象何时可用于后续步骤中的子句。例如,如果查询处理器可以绑定(访问)FROM子句中定义的表或视图,则这些对象及其列可供所有后续步骤使用。相反,因为SELECT子句是步骤8,所以前面的子句不能引用该子句中定义的任何列别名或派生列。但是,它们可以由后续子句引用,例如ORDER BY子句。请注意,语句的实际物理执行由查询处理器确定,并且顺序可能与此列表不同。 从 上 加入 哪里 通过...分组 WITH CUBE或WITH ROLLUP HAVING 选择 不同 订购 TOP

因此,在from部分的子查询中将排名函数作为别名引入,然后您就可以在where部分的别名上设置条件。

祝你好运.. !!