如何使用键集分页?

How to use keyset pagination?

假设我在数据库中总共有 800 行符合条件的行,这些行按列 requisitionid 降序排列。我想在 80 页中显示记录,每页有 10 行。我们使用 requisitionid 作为搜索谓词。那么谓词应该小于还是大于?由于查询将从 UI (Angular + primeNG) 开始,我只想发送一个参数 - requisitionid。如果小于查询,则查询为SELECT ... FROM ... where requisitionid < ?,所以这里我们说的是第一行。如果我们使用大于查询,即 SELECT ... FROM ... where requisitionid > ?,这里我们讨论的是页面的最后一行。

请参考Life without offset

编辑 实际代码:

with topten as (SELECT  DISTINCT TOP 10   
        REQN.CASE_ID
        ,userContact2.BV_First_Name + ' ' + userContact2.BV_Last_Name ReQCreater
        ,REQN.BV_Internal_Job_Title
        ,REQN.BV_Posted_Job_Title as postedJobTitle
        ,REQN.BV_Status
        ,REQN.BV_Taleo_Id
        ,REQN.BV_WD_PositionID
        ,jobcode.BV_Job_Code
        ,loc.BV_LocationCode
        ,loc.BV_LocationName
        ,D.BV_Division_Code AS 'divCode',

        ISNULL(loc.BV_Address1,'') + CASE WHEN ISNULL(loc.BV_Address1,'') = '' THEN '' ELSE ', ' END + ISNULL(loc.BV_Address2,'') + CASE WHEN ISNULL(loc.BV_Address2,'') = '' THEN '' ELSE ', ' END
        + ISNULL(loc.BV_City,'') + CASE WHEN ISNULL(loc.BV_City,'') = '' THEN '' ELSE ', ' END + ISNULL(loc.BV_State,'') + CASE WHEN ISNULL(loc.BV_State,'') = '' THEN '' ELSE (case when ISNULL(loc.BV_ZipCode,'') = '' THEN '' ELSE ', ' END) END
        + ISNULL(loc.BV_ZipCode,'') AS locationAddress
        from dbo.CW_V_REQN as REQN  
        INNER JOIN dbo.CW_TL_Requisition__Location_Master as reqLocLink on REQN.CASE_ID = reqLocLink.FROM_ID 
        INNER JOIN dbo.CW_V_LOCTMAST as loc on loc.CASE_ID = reqLocLink.TO_ID 
        INNER JOIN dbo.CW_TL_UserContactInfo__Location_Master as locUserLink on locUserLink.TO_ID =  loc.CASE_ID 
        INNER JOIN dbo.CW_V_USERCONT as userContact on userContact.CASE_ID = locUserLink.FROM_ID 
        LEFT JOIN dbo.CW_TL_Requisition__Department as reqDeptLink on REQN.CASE_ID = reqDeptLink.FROM_ID 
        INNER JOIN dbo.CW_V_DEPARTME as dept on dept.CASE_ID = reqDeptLink.TO_ID 
        LEFT  JOIN dbo.CW_TL_UserContactInfo__Department_Master as deptUserLink on dept.CASE_ID=deptUserLink.TO_ID 
        INNER JOIN dbo.CW_TL_Requisition__Job_Code as reqJobLink on REQN.CASE_ID = reqJobLink.FROM_ID 
        LEFT JOIN dbo.CW_V_JOBCODE as jobcode on jobcode.CASE_ID = reqJobLink.TO_ID 
        LEFT JOIN dbo.CW_V_USERCONT as userContact2 on (userContact2.BV_Login_Name = REQN.CREATED_BY) 
        LEFT JOIN CW_TL_LocationMaster__Division_Master LD ON (LD.FROM_ID = loc.CASE_ID) 
        LEFT JOIN CW_V_DIVISION D ON (D.CASE_ID = LD.TO_ID) 
        WHERE userContact.BV_Login_Name = @LOGINNAME

        AND REQN.CASE_ID < @MINCASEIDPREVPAGE
        ORDER BY REQN.CASE_ID DESC
        )

select 名列前茅。* , T.* 来自 topten cross join (select min(case_id) as min from topten) as T

如果我理解您的问题,您应该能够在 SELECT 查询末尾使用以下子句:

OFFSET (@Page * 10) ROWS FETCH NEXT 10 ROWS ONLY

如果这不是您要查找的内容,请post您当前的查询,以便我们了解您现在正在做什么。

对于降序键的基于键的分页,WHERE 子句谓词对于下一页应该是 <,对于上一页应该是 >。此外,前一页的 ORDER BY 子句需要 ASC(对于 TOP 谓词)以及外部 DESC(对于降序键显示序列)。下面是一个例子。

--create test table with sample data
CREATE TABLE dbo.YourTable(
    requisitionid int PRIMARY KEY
);
WITH 
     t10 AS (SELECT n FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) t(n))
    ,t1000 AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS num  FROM t10 AS a CROSS JOIN t10 AS b CROSS JOIN t10 AS c)
INSERT INTO dbo.YourTable WITH(TABLOCKX)
SELECT num
FROM t1000
WHERE num <= 800;
GO

--query for first page (page 1) on descending key (returns 800-791)
SELECT TOP(10) requisitionid
FROM YourTable
ORDER BY requisitionid DESC;
GO

--query for next page (page 2) on descending key (returns 790-781)
DECLARE @LastRequisitionIdOnPage int = 791;
SELECT TOP(10) requisitionid
FROM YourTable
WHERE requisitionid < @LastRequisitionIdOnPage
ORDER BY requisitionid DESC;
GO

--query for previous page (page 1) on descending key (returns 800-791)
DECLARE @FirstRequisitionIdOnPage int = 790;
SELECT requisitionid
FROM (
    SELECT TOP(10) requisitionid
    FROM YourTable
    WHERE requisitionid > @FirstRequisitionIdOnPage
    ORDER BY requisitionid ASC
    ) AS prev_page
ORDER BY requisitionid DESC;;
GO