今天做项目的时候发现一个小Bug,引得自己一番思考,在项目中有一个简历信息列表的分页问题,第一页的最后一条信息和第二页的第一条信息是重复的,但是从第二页以后就没有重复的信息了(这个是后来才发现的),就此问题我进行了一番研究,研究结果发现是因为作者在数据访问层对业务逻辑层传递过来的分页起始值再减了一个1,导致第一页的时候sql语句分页的起始值是-1,代码如下:
业务逻辑层相关代码: ResumeDal.ResumesList((page - 1) * showCount, showCount * page); 参数说明:(参数1:分页开始值,参数2:分页结束值)
数据访问层相关代码: int start-=1;(分页开始值)
Sql语句:
select * from [Resume] where [ID] in
(
select top 30 [ID] from
(
select r.ID,row_number()over(order by r.[UpdateTime] desc) as r
from [Resume] r
inner join [User] u on r.UserID = u.ID
left join [Area] c on r.AreaId=c.ID
left join [Subject] s on r.SubId=s.ID
where u.[IsCompany]=0
) as t
where t.r>-1
)
看到这里,我马上想到的就是每次分页都会对起始位置的值进行减1操作,那么不是每页都会有一条重复的数据吗?那么不就有很多的真实数据会看不见吗?(因为页数是根据信息总数除以每页显示的条数得到的,信息总数是真实数据的条数)经过反复测试,我发现只有第一页的最后一条数据和第二页的第一条数据是重复的,从第二页以后的数据就没有重复的了,测试结果与我的第一想法完全不一致,这令我陷入了迷茫当中,为了消除这个疑惑,我静下心来反复测试,终于得到了正解。
当前页 分页开始值 分页结束值 实际获取数据的范围 每页显示的条数 1 -1 30 1-30 30 2 29 59 30-59 30 3 59 89 60-89 30 4 89 119 90-119 30 5 119 149 120-149 30
原理是这样的,获取第一页数据的时候,分页的起始值为-1,作者使用的是row_number进行分页,每页显示的条数固定不变为30,所以实际的取值范围为1-30,这样才满足top 30,当获取第二页的数据时,分页的起始值就变成了29,由于t.r要大于分页开始值,所以实际的取值范围为30-59,观察红色部分可以知道,因为第一页的分页起始值为-1和top 30的原因,导致数据库在获取第一页的数据时取到了原本应该是属于第二页的数据,所以出现了"第一页的最后一条数据和第二页的第一条数据是重复的"这样一种现象,当获取第三页数据时,分页的起始值为59,同理实际的取值范围为60-89,第三页的数据就没有重复了,同样的道理,后面的数据也不会有重复的,所以才会出现"只有第一页的最后一条数据和第二页的第一条数据是重复的,从第二页以后的数据就没有重复的了"这样一种情况,好了,到此已经水落石出了,虽然只是一个小小的问题,却也能让人一番思考,希望自己以后写代码能够想得更多,收获更多。