在mysql的数据库中,我们可以直接使用 limit 5,10 来得到某页的数据。得益于mysql把分页的存储过程封装好了。
有些数据库比如DB2提供了ROW_NUMBER() over(order by) 函数来解决分页问题。比如:DB2
select * from
(SELECT ROW_NUMBER() over( order by PP.OPERATE_DATE desc, PP.OPERATE_ID asc) as row_id, PP.PUBLIC_POLICY_ID, PP.APPLY_NO,PP.POLICY_NO FROM T_PUBLIC_POLICY PP order by PP.OPERATE_DATE desc, PP.OPERATE_ID asc)
as Temp where row_id between 1 and 20
下页就是(21 ~ 40) ............................................
但是有些数据库是没有 此类的方法的,我们大多时候,采用sql来分页。比较多的使用 not in 的方法。
就是:SELECT TOP 页大小 * FROM Table1 WHERE (ID NOT IN (SELECT TOP 页大小*页数 id FROM 表 ORDER BY id)) ORDER BY ID
但这个存储过程有一个致命的缺点,就是它含有NOT IN字样。虽然我可以把它改造为: SELECT TOP 页大小 * FROM Table1 WHERE not exists(select * from (select top (页大小*页数) * from table1 order by id) b where b.id=a.id ) order by id
即,用not exists来代替not in,但二者的执行效率实际上是没有区别的。
在分页算法中,影响我们查询速度的关键因素有两点:TOP和NOT IN。TOP可以提高我们的查询速度,而NOT IN会减慢我们的查询速度,所以要提高我们整个分页算法的速度,就要彻底改造NOT IN,同其他方法来替代它。我们知道,几乎任何字段,我们都可以通过max(字段)或min(字段)来提取某个字段中的最大或最小值,所以如果这个字段不重复,那么就可以利用这些不重复的字段的max或min作为分水岭,使其成为分页算法中分开每页的参照物。在这里,我们可以用操作符“>”或“<”号来完成这个使命,
于是就有了如下分页方案:
select top 页大小 * from table1 where id>(select max (id) from (select top ((页码-1)*页大小) id from table1 order by id) as T) order by id
在选择即不重复值,又容易分辨大小的列时,我们通常会选择主键。
需要说明的是,这种方法,只适合按照特定列排序的情况。如果要求排序的列可能重复,则只好使用 Not In 的方式了。
在执行海量数据的时候,这种方法执行的效率比not in要高。