如何在同一个 select 语句中包含 row_number 的 where 子句?

How to have where clause on row_number within the same select statement?

我无法在同一 select 语句中对行号使用 where 条件。如果我使用不同的 select 语句对行号应用条件,结果将不一致...

 SELECT TOP (@lastrow - 1) c.totalRows
        ,c.ae_effective_enrollment_id
        ,c.[user_id]
        ,c.login_name
        ,c.first_name
        ,c.last_name
        ,cm.courseware_title
        ,cm.courseware_code
        ,@courseware_id assetId
        ,c.enrollment_status_id
        ,CASE 
            WHEN c.enrollment_status_id = 2
                AND c.is_self_enrolled = 0
                THEN 'Admin-' + s.description
            WHEN c.enrollment_status_id = 2
                AND c.is_self_enrolled = 1
                THEN 'Self-' + s.description
            ELSE s.description
            END AS enrollmentStatus
        ,c.is_group
        ,CASE 
            WHEN c.is_self_enrolled = 0
                THEN 1
            ELSE 0
            END is_admin
        ,CASE 
            WHEN c.auma_is_assigned = 1
                THEN 'Admin-assigned'
            WHEN c.auma_is_assigned = 0
                THEN 'Self-assigned'
            ELSE 'No-My-Plan'
            END AS myplanStatus
        , master_assignment_id
        ,ROW_NUMBER() over(partition by cm.courseware_id,c.user_id order by c.is_self_enrolled)as check_row
    FROM enrollmentCTE c
    INNER JOIN dbo.courseware_master cm ON cm.courseware_id = @courseware_id
    LEFT JOIN @statuscodes s ON s.id = c.enrollment_status_id
    WHERE check_row=1 and 
    enrollment_status_id<>4 and
    rownumber > @firstrow
        AND rownumber < @lastrow
    ORDER BY rownumber 

check_row 这里不被识别。请帮助

SELECT totalRows, ae_effective_enrollment_id, user_id, login_name, first_name, last_name, check_row FROM 
(SELECT TOP (@lastrow - 1) c.totalRows as totalRows 
        ,c.ae_effective_enrollment_id as ae_effective_enrollment_id
        ,c.[user_id] as user_id
        ,c.login_name as login_name
        ,c.first_name as first_name
        ,c.last_name as last_name
        ,cm.courseware_title as courseware_title
        ,cm.courseware_code as courseware_code
        ,@courseware_id as assetId
        ,c.enrollment_status_id as enrollment_status_id
        ,CASE 
            WHEN c.enrollment_status_id = 2
                AND c.is_self_enrolled = 0
                THEN 'Admin-' + s.description
            WHEN c.enrollment_status_id = 2
                AND c.is_self_enrolled = 1
                THEN 'Self-' + s.description
            ELSE s.description
            END AS enrollmentStatus
        ,c.is_group
        ,CASE 
            WHEN c.is_self_enrolled = 0
                THEN 1
            ELSE 0
            END is_admin
        ,CASE 
            WHEN c.auma_is_assigned = 1
                THEN 'Admin-assigned'
            WHEN c.auma_is_assigned = 0
                THEN 'Self-assigned'
            ELSE 'No-My-Plan'
            END AS myplanStatus
        , master_assignment_id
        ,ROW_NUMBER() over(partition by cm.courseware_id,c.user_id order by c.is_self_enrolled)as check_row
    FROM enrollmentCTE c
    INNER JOIN dbo.courseware_master cm ON cm.courseware_id = @courseware_id
    LEFT JOIN @statuscodes s ON s.id = c.enrollment_status_id
    WHERE enrollment_status_id<>4 and
    rownumber > @firstrow
        AND rownumber < @lastrow
    ORDER BY rownumber ) t where check_row = 1

注意 - 在第一个 select 语句

中添加所有列名

SQL执行顺序。

  1. FROM clause
  2. WHERE clause
  3. GROUP BY clause
  4. HAVING clause
  5. SELECT clause
  6. ORDER BY clause

check_row 别名是在 select 部分创建的,因此它在上下文中尚不存在

编辑 做了一些测试。似乎无法正确处理。作为临时解决方案,您可以尝试将

ROW_NUMBER() over(...

where 子句中还有

编辑: MSDN website 的另一个选项是

Returning a subset of rows

The following example calculates row numbers for all rows in the SalesOrderHeader table in the order of the OrderDate and returns only rows 50 to 60 inclusive.

USE AdventureWorks2012;
GO
WITH OrderedOrders AS
(
    SELECT SalesOrderID, OrderDate,
    ROW_NUMBER() OVER (ORDER BY OrderDate) AS RowNumber
    FROM Sales.SalesOrderHeader 
) 
SELECT SalesOrderID, OrderDate, RowNumber  
FROM OrderedOrders 
WHERE RowNumber BETWEEN 50 AND 60;

使用 CTE 使您的查询基于另一个

;WITH CTE AS(
    SELECT  c.totalRows
            ,c.ae_effective_enrollment_id
            ,c.[user_id]
            ,c.login_name
            ,c.first_name
            ,c.last_name
            ,cm.courseware_title
            ,cm.courseware_code
            ,@courseware_id assetId
            ,c.enrollment_status_id
            ,CASE 
                WHEN c.enrollment_status_id = 2
                    AND c.is_self_enrolled = 0
                    THEN 'Admin-' + s.description
                WHEN c.enrollment_status_id = 2
                    AND c.is_self_enrolled = 1
                    THEN 'Self-' + s.description
                ELSE s.description
                END AS enrollmentStatus
            ,c.is_group
            ,CASE 
                WHEN c.is_self_enrolled = 0
                    THEN 1
                ELSE 0
                END is_admin
            ,CASE 
                WHEN c.auma_is_assigned = 1
                    THEN 'Admin-assigned'
                WHEN c.auma_is_assigned = 0
                    THEN 'Self-assigned'
                ELSE 'No-My-Plan'
                END AS myplanStatus
            , master_assignment_id
            ,ROW_NUMBER() over(partition by cm.courseware_id,c.user_id order by c.is_self_enrolled) as check_row
    FROM enrollmentCTE c
    INNER JOIN dbo.courseware_master cm ON cm.courseware_id = @courseware_id
    LEFT JOIN @statuscodes s ON s.id = c.enrollment_status_id
    WHERE enrollment_status_id<>4
    AND rownumber > @firstrow
    AND rownumber < @lastrow
)
SELECT TOP (@lastrow - 1) *
FROM CTE
WHERE check_row = 1
ORDER BY rownumber