在SQL中进行分页,主键没有中断

时间:2017-04-05 07:38:42

标签: sql sql-server

我是Stackoverflow的新手。如果我犯了一些错误,请原谅我。

我在SQL中有以下数据。

Row No.  Customer No.  Customer Name
------------------------------------------------------------
1        1234          ABCD
2        1234          ABCD
3        1234          ABCD
4        6789          WXYZ
5        6789          WXYZ
6        3456          OPQR
7        4567          JKLM

我需要使用以下约束

来分页上述数据
  • 页面大小:4条记录
  • 如果客户没有。在两页之间分裂,然后是新客户。应该转到下一页。

所需的输出:

每页分页4条记录

第1页

Row No.  Customer No.  Customer Name
------------------------------------------------------------
1        1234          ABCD
2        1234          ABCD
3        1234          ABCD

第二页

Row No.  Customer No.  Customer Name
------------------------------------------------------------
4        6789          WXYZ
5        6789          WXYZ
6        3456          OPQR
7        4567          JKLM

请帮忙。

3 个答案:

答案 0 :(得分:0)

您可以使用任何限制读取页面大小+1记录,如果最后一条记录和最后一条记录具有相同的客户名称,则只使用HAVING过滤掉客户。

可能很棘手,取决于您使用的数据库,可以在表示层轻松完成

答案 1 :(得分:0)

Declare @PageNumber INT = 1,  @PageSize   INT = 4
;with cte1(RowNo,CustomerNo,CustomerName)
AS
(
Select 1,1234,'ABCD' union all
Select 2,1234,'ABCD' union all
Select 3,1234,'ABCD' union all
Select 4,6789,'WXYZ' union all
Select 5,6789,'WXYZ' union all
Select 6,3456,'OPQR' union all
Select 7,4567,'JKLM' 
)
select * from cte1 order by RowNo
 OFFSET @PageSize * (@PageNumber - 1) ROWS
      FETCH NEXT @PageSize ROWS ONLY

答案 2 :(得分:0)

这可以做到,而不是使用递归CTE复杂化。

对于样本数据,我使用了其他答案的查询

WITH cte1(RowNo,CustomerNo,CustomerName)
AS
(
    SELECT 1,1234,'ABCD' UNION ALL
    SELECT 2,1234,'ABCD' UNION ALL
    SELECT 3,1234,'ABCD' UNION ALL
    SELECT 4,6789,'WXYZ' UNION ALL
    SELECT 5,6789,'WXYZ' UNION ALL
    SELECT 6,3456,'OPQR' UNION ALL
    SELECT 7,4567,'JKLM' 
)
SELECT * INTO #table FROM cte1

我再添加一行用reapaing用户将其拆分为第3页

INSERT #table (RowNo, CustomerNo, CustomerName) VALUES (8,3456,'OPQR')

这是解决方案。我已经提出一些意见来解释部分

WITH CTE_Source AS 
(
    --I use this to add RN column simply beacuse I can't trust that rowNo column will have no gaps
    SELECT *
    , ROW_NUMBER() OVER (ORDER BY RowNo) RN 
    FROM #table t
)
, CTE_R AS 
(
    --First part is select of first row
    SELECT s.RowNo
         , s.CustomerNo
         , s.CustomerName
         , s.RN
         , 1 AS Grp --this is a current group of rows
         , 1 AS Cnt --counter of how many rows group have
    FROM CTE_Source s WHERE RN = 1
    UNION ALL
    --subsequent select is for next row
    SELECT 
         s.RowNo
         , s.CustomerNo
         , s.CustomerName
         , s.RN 
         -- increase group when different customer 
         , CASE WHEN s.CustomerNo = r.CustomerNo THEN r.Grp ELSE r.Grp+Cnt END
         -- increase counter when same customer
         , CASE WHEN s.CustomerNo = r.CustomerNo THEN r.Cnt + 1 ELSE 1 END
    FROM CTE_R r
    INNER JOIN CTE_Source s ON s.RN = r.Rn + 1

)
, CTE_Paging AS 
(
    SELECT *
    , CEILING((r.Grp + r.Cnt) / 4.) AS Page -- replace 4 with your page size
    FROM CTE_R r
)
SELECT * FROM CTE_Paging --Just add WHERE Page = if you want specific page
OPTION (MAXRECURSION 0) -- for unlimited recursion if you have more than 100 rows