大坑之分页

发表日期:2022-08-20 10:46:18 | 来源: | | 浏览(686) 分类:SQLServer

SQLServer的分页实现实在是太恶心了,不像mysql有limit 语句,也不像oracle有分页函数支持,完全需要自己逻辑实现。


SQLserver主流的三种方式:

方式1:利用ROW_NUMBER()函数,给每一行加行号,然后再between 开始行号 and 结束行号,例如:

SELECT T1.*
FROM (SELECT result.*, ROW_NUMBER() OVER ( ORDER BY rand()) AS ROW_NUMBER
      FROM (SELECT * FROM [Users] WHERE ustate = 1) AS result
     ) AS T1
WHERE (T1.ROW_NUMBER BETWEEN 1 AND 10)

要注意的是ROW_NUMBE函数只有SQLServer2008才开始有,之前我做过的一个老项目是SERVER 2005的不支持,太坑人了,不过好在现在大多数项目也不会用这么老的库。看似比较复杂难懂,实际上是用起来改动最小的方式,只需要把 最内侧的那句select换成你的就行了,其它都是固定格式


方式2:利用TOP关键字和id not in,每次查前十条 然后在where条件里排除掉 前面几页的N*10条,例如:

SELECT top 10 *
FROM [Users]
WHERE ustate = 1
  and uid not in(
  SELECT  top ( N * 10) UID FROM [Users] WHERE ustate = 1 --N:0第一页 1第二页 类推
  )

外层的where条件必须和内层的where条件一样。not in 适合行数较小的表,如果是行数过大的表,那么查询后面的页会很慢,看似写法简单但如果查询条件很复杂,看起来乱,不是很推荐。


方式3:利用id的自增排序后比大小

select top 10 *
from Users
where uid >
      (
          select isnull(max(uid),0) from (
                  select top N uid from Users order by uid  --N:0第一页 1第二页 类推
          ) A
      )
order by uid

前提是你的id是自增列


当然现在还有其它方式,大同小异吧,总之原理就是排除前些一页的数据然后再去 TOP 条数。

比较推荐方式一。


说些题外的话,不知道微软是不是觉得自己的数据库性能好的不得了不需要分页直接查全部就行……现实情况亦如此,我认识的好几个SQLserver使用10年+且SQL很厉害的人,并不知SQLserver如何分页,这么多年以来一直是万条数据以内的表查全部用前端分页,数据量大的就是TOP 500或 TOP 1000 …… 显示不到的那么客户就用搜索让目标数据能进入到TOP 500 ……,要是你想看全部,那么不好意思,太久的数据不支持查询…… 15年+的老项目了,数据量大所以很多页面加载都非常慢。

形成这样的原因我不认为程序员的问题,而是工具做的不人性,因为SQLserver本身并不提供分页的直接支持,且微软系的编程语言VB、asp、.net等使用SQLserver,分页是直接有语言自带的分页函数,以至于那个年代的程序员接触不到需要手写SQL分页,致使很多人以为也是先查了全表然后代码里实现的截取指定行分页的……因此在写SQL的时候没有SQL分页的概念。这并不是技术问题,而是不同年代所接收的信息不对称。

集速网 copyRight © 2015-2022 宁ICP备15000399号-1 宁公网安备 64010402001209号
与其临渊羡鱼,不如退而结网
欢迎转载、分享、引用、推荐、收藏。