最近我遇到了一些奇怪的问题。我有两个简单的查询,其中一个使用TOP X,另一个使用ROW_NUMBER,然后选择rowNumber在1和X之间的项目,并且它们都按相同的列排序,但结果完全不同。
例如,假设我们有一个简单的DB,如下所示,带有一些虚拟数据:
CREATE TABLE [dbo].[Test](
[Id] [int] IDENTITY(1,1) NOT NULL,
[NDate] [datetime] NOT NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
SET IDENTITY_INSERT [dbo].[Test] ON
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (1, '2011-08-24 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (2, '2011-08-24 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (3, '2011-08-24 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (4, '2011-08-24 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (5, '2011-08-21 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (6, '2011-08-21 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (7, '2011-08-21 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (8, '2011-08-21 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (9, '2011-08-21 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (10, '2011-08-21 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (11, '2011-08-21 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (12, '2011-08-21 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (13, '2011-08-21 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (14, '2011-08-21 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (15, '2011-08-21 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (16, '2011-08-21 00:00:00.000')
SET IDENTITY_INSERT [dbo].[Test] OFF
现在,如果我们执行以下查询,我们将得到不同的结果。如果我们使用TOP 10,我们将得到以下结果:
SELECT TOP 10 [Id],[NDate] FROM [Test] order by NDate desc
RESULT=>
Id NDate
4 2011-08-24 00:00:00.000
3 2011-08-24 00:00:00.000
2 2011-08-24 00:00:00.000
1 2011-08-24 00:00:00.000
11 2011-08-21 00:00:00.000
10 2011-08-21 00:00:00.000
9 2011-08-21 00:00:00.000
8 2011-08-21 00:00:00.000
7 2011-08-21 00:00:00.000
6 2011-08-21 00:00:00.000
select id,NDate from (
select ROW_NUMBER() over (order by NDate DESC) as RNumber, Id,NDate
from Test) as t
where RNumber between 1 and 10
RESULT=>
id NDate
1 2011-08-24 00:00:00.000
2 2011-08-24 00:00:00.000
3 2011-08-24 00:00:00.000
4 2011-08-24 00:00:00.000
5 2011-08-21 00:00:00.000
6 2011-08-21 00:00:00.000
7 2011-08-21 00:00:00.000
8 2011-08-21 00:00:00.000
9 2011-08-21 00:00:00.000
10 2011-08-21 00:00:00.000
问题是,当您使用LINQ to SQL,并且想要进行分页时,用于选择第一页的生成查询将是TOP X,而对于其他页面将使用ROW_NUMBER,结果是,某些项目将永远不会出现在列表中。
答案 0 :(得分:4)
您需要实施二级排序。
示例:强>
select id,NDate from (
select ROW_NUMBER() over (order by NDate DESC, id) as RNumber, Id,NDate -- Note: NDate DESC, id
from Test) as t
where RNumber between 1 and 10
示例:强>
SELECT TOP 10 [Id],[NDate] FROM [Test] order by NDate desc, ID -- Note: NDate DESC, id
否则,您可能会期望每个唯一NDate
的随机记录。
如果您希望每个查询都有相同的记录,则必须指定该二级排序列。
答案 1 :(得分:1)
我同意@ hamlin11,但更简单地说: - )
在第一个示例中,您按
排序order by NDate desc
/* to get same results as example 2, change this to
order by NDate desc, id
*/
和第二个
order by NDate DESC, id
在第二个示例中,您按ID排序,这就是ID列按顺序排列的原因,您在第一个示例中没有这样做。
使用这样的数据可能会更好,这样您就可以更清楚地看到发生了什么:
/****** Object: Table [dbo].[Test] Script Date: 08/27/2011 07:56:29 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Test](
[Id] [int] IDENTITY(1,1) NOT NULL,
[NDate] [datetime] NOT NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[Test] ON
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (1, '2011-08-10 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (2, '2011-08-11 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (3, '2011-08-12 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (4, '2011-08-13 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (5, '2011-08-14 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (6, '2011-08-15 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (7, '2011-08-16 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (8, '2011-08-31 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (9, '2011-08-30 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (10, '2011-08-29 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (11, '2011-08-28 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (12, '2011-08-27 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (13, '2011-08-26 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (14, '2011-08-25 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (15, '2011-08-24 00:00:00.000')
INSERT [dbo].[Test] ([Id], [NDate]) VALUES (16, '2011-08-23 00:00:00.000')
SET IDENTITY_INSERT [dbo].[Test] OFF