Using ranking-function derived column in where clause (SQL Server 2008)

后端 未结 3 842
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-02-15 12:31

Hoping this is trivial for a SQL-Ninja... Been trying to get the following query working:

This is for SQL Server 2008

SELECT 
    ROW_NUMBER() OVER (ORD         


        
相关标签:
3条回答
  • 2021-02-15 13:18

    You must move the WHERE operator above the project list where RowNumber column is created. Use a derived table or a CTE:

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

    the equivalent CTE is:

    WITH cte AS (
    SELECT *, ROW_NUMBER() OVER (...) as RowNumber
           FROM ...)
    SELECT * FROM cte 
    WHERE RowNumber = ...   
    
    0 讨论(0)
  • 2021-02-15 13:34

    The Problem with the Query comes in because of the the fault in the Logical processing order. This is the logical processing order specified in MSDN dev Network.

    Logical Processing Order of the SELECT statement The following steps show the logical processing order, or binding order, for a SELECT statement. This order determines when the objects defined in one step are made available to the clauses in subsequent steps. For example, if the query processor can bind to (access) the tables or views defined in the FROM clause, these objects and their columns are made available to all subsequent steps. Conversely, because the SELECT clause is step 8, any column aliases or derived columns defined in that clause cannot be referenced by preceding clauses. However, they can be referenced by subsequent clauses such as the ORDER BY clause. Note that the actual physical execution of the statement is determined by the query processor and the order may vary from this list. FROM ON JOIN WHERE GROUP BY WITH CUBE or WITH ROLLUP HAVING SELECT DISTINCT ORDER BY TOP

    So introduce the ranking function as an alias in the subquery in the from section and then you will be able to set a condition on the alias in the where section.

    Good Luck..!!

    0 讨论(0)
  • 2021-02-15 13:38

    The Window Functions (of which ROW_NUMBER is the best know) are filled in very late in the query, well after the WHERE clause. Therefore you have to nest it too, in order to filter on it:

    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
    

    You can also put them in CTE's or Views to get the same effect.

    0 讨论(0)
提交回复
热议问题