【问题标题】:SQL Server 2012 PaginationSQL Server 2012 分页
【发布时间】:2016-05-21 10:01:31
【问题描述】:

我有这个表定义

CREATE TABLE [dbo].[Earnings](
    [Name] [nvarchar](50) NOT NULL,
    [Date] [datetime] NOT NULL,
    [Earnings] [decimal](18, 2) NOT NULL
)

我有这个样本数据

INSERT INTO [dbo].[Earnings] ([name], [Date], [Earnings])
VALUES
('person1',  datefromparts(2015, 9, 1), 9.01),
('person1',  datefromparts(2015, 10, 5), 10.05),
('person1',  datefromparts(2015, 11, 21), 11.21),
('person1',  datefromparts(2016, 1, 11), 1.12),
('person1',  datefromparts(2016, 3, 13), 3.13),
('person1',  datefromparts(2016, 5, 15), 5.15),
('person2',  datefromparts(2016, 6, 16), 6.16),
('person2',  datefromparts(2016, 8, 18), 8.18)

当我进行分页时,我总是得到以下两个 sql 语句的相同结果,我想知道这个问题的原因是什么?有什么可能的方法来解决它?

SELECT  *  FROM [dbo].Earnings  order by Name   OFFSET 0 ROWS FETCH NEXT 2 ROWS ONLY ;
SELECT  *  FROM [dbo].Earnings  order by Name   OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY ;

两次执行的结果

Name    Date    Earnings
person1 2015-11-21 00:00:00.000 11.21
person1 2015-10-05 00:00:00.000 10.05

【问题讨论】:

  • 排序依据应该是确定性的
  • 按名称、日期使用顺序
  • 如果您只按名称排序,SQL 可以选择它想要的具有该名称的前两行,并且不必每次都遵循相同的顺序。

标签: sql sql-server sql-server-2012 pagination


【解决方案1】:

Order by 应该是确定性的。这意味着如果任何列包含相同的值并且在 order by 子句中使用,sql 将选择/可以选择任何行。所以确定性排序,按列排序应该是唯一的。

在你的情况下,使用

SELECT  *  FROM [dbo].Earnings  order by Name,date   OFFSET 0 ROWS FETCH NEXT 2 ROWS ONLY ;
SELECT  *  FROM [dbo].Earnings  order by Name,date   OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY ;

【讨论】:

    【解决方案2】:

    提供的答案是正确的。但是,我的建议是在您的表中添加一个 PrimaryKey 并使用它:

    CREATE TABLE [dbo].[Earnings](
        EarningId INT NOT NULL CONSTRAINT PK_Earnings PRIMARY KEY,  -- can also be added IDENTITY(1, 1)
        [Name] [nvarchar](50) NOT NULL,
        [Date] [datetime] NOT NULL,
        [Earnings] [decimal](18, 2) NOT NULL
    )
    

    查询变得简单,我认为也更快,因为排序将基于聚集索引完成:

    SELECT * FROM [dbo].Earnings  order by EarningId OFFSET 0 ROWS FETCH NEXT 2 ROWS ONLY;
    SELECT * FROM [dbo].Earnings  order by EarningId OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY;
    

    添加PK 还有一个主要优点是每条记录都可以清楚地识别。

    作为说明,在按列排序之前,我还注意到按SELECT 1 排序似乎可以解决问题:

    SELECT * FROM [dbo].Earnings  order by (SELECT 1) OFFSET 0 ROWS FETCH NEXT 2 ROWS ONLY;
    SELECT * FROM [dbo].Earnings  order by (SELECT 1) EarningId OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY;
    

    但是,我不会依赖这个顺序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-04
      • 2020-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-26
      • 1970-01-01
      相关资源
      最近更新 更多