SQL Row_Number() function in Where Clause

后端 未结 10 1476
野性不改
野性不改 2020-12-02 16:11

I found one question answered with the Row_Number() function in the where clause. When I tried one query, I was getting the following error:

相关标签:
10条回答
  • 2020-12-02 16:44

    based on OP's answer to question:

    Please see this link. Its having a different solution, which looks working for the person who asked the question. I'm trying to figure out a solution like this.

    Paginated query using sorting on different columns using ROW_NUMBER() OVER () in SQL Server 2005

    ~Joseph

    "method 1" is like the OP's query from the linked question, and "method 2" is like the query from the selected answer. You had to look at the code linked in this answer to see what was really going on, since the code in the selected answer was modified to make it work. Try this:

    DECLARE @YourTable table (RowID int not null primary key identity, Value1 int, Value2 int, value3 int)
    SET NOCOUNT ON
    INSERT INTO @YourTable VALUES (1,1,1)
    INSERT INTO @YourTable VALUES (1,1,2)
    INSERT INTO @YourTable VALUES (1,1,3)
    INSERT INTO @YourTable VALUES (1,2,1)
    INSERT INTO @YourTable VALUES (1,2,2)
    INSERT INTO @YourTable VALUES (1,2,3)
    INSERT INTO @YourTable VALUES (1,3,1)
    INSERT INTO @YourTable VALUES (1,3,2)
    INSERT INTO @YourTable VALUES (1,3,3)
    INSERT INTO @YourTable VALUES (2,1,1)
    INSERT INTO @YourTable VALUES (2,1,2)
    INSERT INTO @YourTable VALUES (2,1,3)
    INSERT INTO @YourTable VALUES (2,2,1)
    INSERT INTO @YourTable VALUES (2,2,2)
    INSERT INTO @YourTable VALUES (2,2,3)
    INSERT INTO @YourTable VALUES (2,3,1)
    INSERT INTO @YourTable VALUES (2,3,2)
    INSERT INTO @YourTable VALUES (2,3,3)
    INSERT INTO @YourTable VALUES (3,1,1)
    INSERT INTO @YourTable VALUES (3,1,2)
    INSERT INTO @YourTable VALUES (3,1,3)
    INSERT INTO @YourTable VALUES (3,2,1)
    INSERT INTO @YourTable VALUES (3,2,2)
    INSERT INTO @YourTable VALUES (3,2,3)
    INSERT INTO @YourTable VALUES (3,3,1)
    INSERT INTO @YourTable VALUES (3,3,2)
    INSERT INTO @YourTable VALUES (3,3,3)
    SET NOCOUNT OFF
    
    DECLARE @PageNumber     int
    DECLARE @PageSize       int
    DECLARE @SortBy         int
    
    SET @PageNumber=3
    SET @PageSize=5
    SET @SortBy=1
    
    
    --SELECT * FROM @YourTable
    
    --Method 1
    ;WITH PaginatedYourTable AS (
    SELECT
        RowID,Value1,Value2,Value3
            ,CASE @SortBy
                 WHEN  1 THEN ROW_NUMBER() OVER (ORDER BY Value1 ASC)
                 WHEN  2 THEN ROW_NUMBER() OVER (ORDER BY Value2 ASC)
                 WHEN  3 THEN ROW_NUMBER() OVER (ORDER BY Value3 ASC)
                 WHEN -1 THEN ROW_NUMBER() OVER (ORDER BY Value1 DESC)
                 WHEN -2 THEN ROW_NUMBER() OVER (ORDER BY Value2 DESC)
                 WHEN -3 THEN ROW_NUMBER() OVER (ORDER BY Value3 DESC)
             END AS RowNumber
        FROM @YourTable
        --WHERE
    )
    SELECT
        RowID,Value1,Value2,Value3,RowNumber
            ,@PageNumber AS PageNumber, @PageSize AS PageSize, @SortBy AS SortBy
        FROM PaginatedYourTable
        WHERE RowNumber>=(@PageNumber-1)*@PageSize AND RowNumber<=(@PageNumber*@PageSize)-1
        ORDER BY RowNumber
    
    
    
    --------------------------------------------
    --Method 2
    ;WITH PaginatedYourTable AS (
    SELECT
        RowID,Value1,Value2,Value3
            ,ROW_NUMBER() OVER
             (
                 ORDER BY
                     CASE @SortBy
                         WHEN  1 THEN Value1
                         WHEN  2 THEN Value2
                         WHEN  3 THEN Value3
                     END ASC
                    ,CASE @SortBy
                         WHEN -1 THEN Value1
                         WHEN -2 THEN Value2
                         WHEN -3 THEN Value3
                     END DESC
             ) RowNumber
        FROM @YourTable
        --WHERE  more conditions here
    )
    SELECT
        RowID,Value1,Value2,Value3,RowNumber
            ,@PageNumber AS PageNumber, @PageSize AS PageSize, @SortBy AS SortBy
        FROM PaginatedYourTable
        WHERE 
            RowNumber>=(@PageNumber-1)*@PageSize AND RowNumber<=(@PageNumber*@PageSize)-1
            --AND more conditions here
        ORDER BY
            CASE @SortBy
                WHEN  1 THEN Value1
                WHEN  2 THEN Value2
                WHEN  3 THEN Value3
            END ASC
           ,CASE @SortBy
                WHEN -1 THEN Value1
                WHEN -2 THEN Value2
                WHEN -3 THEN Value3
            END DESC
    

    OUTPUT:

    RowID  Value1 Value2 Value3 RowNumber  PageNumber  PageSize    SortBy
    ------ ------ ------ ------ ---------- ----------- ----------- -----------
    10     2      1      1      10         3           5           1
    11     2      1      2      11         3           5           1
    12     2      1      3      12         3           5           1
    13     2      2      1      13         3           5           1
    14     2      2      2      14         3           5           1
    
    (5 row(s) affected
    
    RowID  Value1 Value2 Value3 RowNumber  PageNumber  PageSize    SortBy
    ------ ------ ------ ------ ---------- ----------- ----------- -----------
    10     2      1      1      10         3           5           1
    11     2      1      2      11         3           5           1
    12     2      1      3      12         3           5           1
    13     2      2      1      13         3           5           1
    14     2      2      2      14         3           5           1
    
    (5 row(s) affected)
    
    0 讨论(0)
  • 2020-12-02 16:44
    WITH MyCte AS 
    (
        select 
           employee_id,
           RowNum = row_number() OVER (order by employee_id)
        from V_EMPLOYEE 
    )
    SELECT  employee_id
    FROM    MyCte
    WHERE   RowNum > 0
    ORDER BY employee_id
    
    0 讨论(0)
  • 2020-12-02 16:48
    Select * from 
    (
        Select ROW_NUMBER() OVER ( order by Id) as 'Row_Number', * 
        from tbl_Contact_Us
    ) as tbl
    Where tbl.Row_Number = 5
    
    0 讨论(0)
  • 2020-12-02 16:49

    In response to comments on rexem's answer, with respect to whether a an inline view or CTE would be faster I recast the queries to use a table I, and everyone, had available: sys.objects.

    WITH object_rows AS (
        SELECT object_id, 
            ROW_NUMBER() OVER ( ORDER BY object_id) RN
        FROM sys.objects)
    SELECT object_id
    FROM object_rows
    WHERE RN > 1
    
    SELECT object_id
    FROM (SELECT object_id, 
            ROW_NUMBER() OVER ( ORDER BY object_id) RN
        FROM sys.objects) T
    WHERE RN > 1
    

    The query plans produced were exactly the same. I would expect in all cases, the query optimizer would come up with the same plan, at least in simple replacement of CTE with inline view or vice versa.

    Of course, try your own queries on your own system to see if there is a difference.

    Also, row_number() in the where clause is a common error in answers given on Stack Overflow. Logicaly row_number() is not available until the select clause is processed. People forget that and when they answer without testing the answer, the answer is sometimes wrong. (A charge I have myself been guilty of.)

    0 讨论(0)
  • 2020-12-02 16:52
     select salary from (
     select  Salary, ROW_NUMBER() over (order by Salary desc) rn from Employee 
     ) t where t.rn = 2
    
    0 讨论(0)
  • 2020-12-02 16:59

    To get around this issue, wrap your select statement in a CTE, and then you can query against the CTE and use the windowed function's results in the where clause.

    WITH MyCte AS 
    (
        select   employee_id,
                 RowNum = row_number() OVER ( order by employee_id )
        from     V_EMPLOYEE 
        ORDER BY Employee_ID
    )
    SELECT  employee_id
    FROM    MyCte
    WHERE   RowNum > 0
    
    0 讨论(0)
提交回复
热议问题