快速分页sql及程序实现 之配餐系统的开发
2011-11-19 17:28
507 查看
本文所要讲的是在配餐系统开发中,所使用的分页方法和当时的思考——实际上这个配餐系统软件在今年2月份已经做完,这篇博客也本应该早写出来了,但因为各种原因:之前忙和之后的状态不佳(主要还是个人原因,如果想写,时间不挤也是有的,懒散了),导致此文一直迟迟未写。转到正题,说到分页——最直接或普遍的,我们需要考虑的是分页SQL的写法,像select top .... id(表主键)> 或 not in...,这样的写法算是我们最常见和使用的(像学习编程或项目经验很少时),而其中 id(表主键)> 比 not in 的效率要高,但当数据量比较大时(几万或几十万条的信息),查询速度就会比较明显的降低(我这里特制的是access数据库下,对于其它高级或性能优化比较好的数据库mysql,sqlserver等数据库下可能影响比较小)。我做的配餐系统这个项目,使用的是access数据库,最开始采用的id(表主键)>的分页方法,在导入近万条的食物数据后,查询速度就明显的下降,导致界面假死,这样即使在数据不增加的情况下,用户体验性也不好;问题必须要解决,于是考虑改进和优化——需要找一个更高效的分页算法。
(软件中的界面图)
看上图,现在想要查出最后一页的记录,你会怎么写查询SQL? 如果按上面的的两种方式,就必须先查询出n-1页的记录或其中最大的主键id,但我如果直接查询最后一页的记录——select top 最后一页的记录数(根据总记录数和pageSize可以得出),哪种方式速度更快,想必你很容易能看出来!(其实,我们可以将查询看作是寻找或走路,从最后一条记录查询最后一页的记录当然更快), 于是,上图对应到分页,就可以得出,如果是查询页<=中间页的,从第一页开始查询更快,而查询页>中间页的,从最后一页开始查询更快。说的比较模糊,直接贴出代码如下:
看了代码,你会发现其实其中的分页查询并没有用到什么其它的数据库函数或新的方法,变的只是查询的策略——想法。
好了,就此结尾。希望此文或文中的考虑问题的想法能对你有所帮助,也希望大家能多提意见和分享你的快速查询方面的经验!
(软件中的界面图)
看上图,现在想要查出最后一页的记录,你会怎么写查询SQL? 如果按上面的的两种方式,就必须先查询出n-1页的记录或其中最大的主键id,但我如果直接查询最后一页的记录——select top 最后一页的记录数(根据总记录数和pageSize可以得出),哪种方式速度更快,想必你很容易能看出来!(其实,我们可以将查询看作是寻找或走路,从最后一条记录查询最后一页的记录当然更快), 于是,上图对应到分页,就可以得出,如果是查询页<=中间页的,从第一页开始查询更快,而查询页>中间页的,从最后一页开始查询更快。说的比较模糊,直接贴出代码如下:
#region 分页查询的SQL 2 3 ///<summary> /// 返回 分页查询的SQL ///</summary> ///<param name="pageSize">每页要显示的记录的数目</param> ///<param name="pageCount">页面的总数</param> ///<param name="pageIndex">要显示的页的索引</param> ///<param name="recordCount">当前要分页的记录总数</param> ///<param name="tableName">要查询的数据表</param> ///<param name="queryFields">要查询的字段</param> ///<param name="primaryKey">主键字段</param> ///<param name="ascending">是否为升序排列</param> ///<param name="condition">查询的筛选条件</param> ///<param name="order">查询的排序条件,一般按 主键 排序</param> ///<returns></returns> public static string PageView_Com(int pageSize,int pageCount,int pageIndex,int recordCount,string tableName,string queryFields,string primaryKey,bool ascending,string condition,string order) { if (string.IsNullOrEmpty(condition)) condition = " 1=1 "; //if (string.IsNullOrEmpty(order)) // order = PrimaryKey; int firstIndex = 0; //第一页的索引 if (pageIndex <= firstIndex) return String.Format("SELECT top {0} {1} FROM {2} where {3} order by {4} {5} ", pageSize, queryFields, tableName, condition, primaryKey, GetSortType(ascending)); 28 StringBuilder sql = new StringBuilder(); int middleIndex = GetMidPageIndex(pageCount); //中间页的索引 int lastIndex = pageCount - 1; //最后一页的索引 if (pageIndex > firstIndex && pageIndex <= middleIndex) { #region 前半部分查询 sql.Append("SELECT TOP ").Append(pageSize).Append("") .Append(queryFields).Append(" FROM ").Append(tableName) .Append(" WHERE ").Append(primaryKey); if (ascending) sql.Append(" > (").Append(" SELECT MAX("); else sql.Append(" < (").Append(" SELECT MIN("); sql.Append(primaryKey).Append(") FROM ( SELECT TOP ") .Append(pageSize * pageIndex).Append("").Append(primaryKey) .Append(" FROM ").Append(tableName); if (condition != String.Empty) sql.Append(" WHERE ").Append(condition); sql.Append(" ORDER BY ").Append(primaryKey).Append("") .Append(GetSortType(ascending)).Append(" ) TableA )"); if (condition != String.Empty) sql.Append(" AND ").Append(condition); sql.Append(" ORDER BY ").Append(primaryKey).Append("") .Append(GetSortType(ascending)); #endregion } else if (pageIndex > middleIndex && pageIndex < lastIndex) { #region 后半部分查询 sql.Append("SELECT * FROM (").Append("SELECT TOP ").Append(pageSize) .Append("").Append(queryFields).Append(" FROM ").Append(tableName) .Append(" WHERE ").Append(primaryKey); if (ascending) sql.Append(" < (").Append(" SELECT MIN("); else sql.Append(" > (").Append(" SELECT MAX("); sql.Append(primaryKey).Append(") FROM ( SELECT TOP ") .Append(recordCount - pageSize * (pageIndex + 1)).Append("") .Append(primaryKey).Append(" FROM ").Append(tableName); if (condition != String.Empty) sql.Append(" WHERE ").Append(condition); sql.Append(" ORDER BY ").Append(primaryKey).Append("") .Append(GetSortType(!ascending)).Append(" ) TableA ) "); if (condition != String.Empty) sql.Append(" and ").Append(condition); sql.Append(" ORDER BY ").Append(primaryKey).Append("").Append(GetSortType(!ascending)); sql.Append(" ) TableB ORDER BY ").Append(primaryKey).Append("").Append(GetSortType(ascending)); #endregion } else if (pageIndex >= lastIndex) { #region 最后一页 sql.Append("SELECT * FROM ( SELECT TOP ").Append(recordCount - pageSize * lastIndex) .Append("").Append(queryFields).Append(" FROM ").Append(tableName); if (condition != String.Empty) sql.Append(" WHERE ").Append(condition); sql.Append(" ORDER BY ").Append(primaryKey).Append("").Append(GetSortType(!ascending)); sql.Append(") as TableA ORDER BY ").Append(primaryKey).Append("").Append(GetSortType(ascending)); #endregion } return sql.ToString(); } 92 ///<summary> /// 计算中间页的页索引 ///</summary> ///<param name="pageCount"></param> ///<returns></returns> private static int GetMidPageIndex(int pageCount) { return (int)Math.Ceiling((double)pageCount / 2) - 1; } ///<summary> /// 获取排序的方式("ASC"表示升序,"DESC"表示降序) ///</summary> ///<param name="ascending"></param> ///<returns></returns> private static String GetSortType(bool ascending) { return (ascending ? "ASC" : "DESC"); } #endregion
看了代码,你会发现其实其中的分页查询并没有用到什么其它的数据库函数或新的方法,变的只是查询的策略——想法。
好了,就此结尾。希望此文或文中的考虑问题的想法能对你有所帮助,也希望大家能多提意见和分享你的快速查询方面的经验!
相关文章推荐
- 快速分页sql及程序实现 之配餐系统的开发
- 使用系统存储过程实现的通用分页存储过程.sql
- WinForm"搜索提示效果(不错的)实现" 之 配餐系统的开发
- Apache+PHP 实现基于Slim的REST框架 调用系统命令或自己开发的程序
- 如何用Baas快速在腾讯云上开发小程序-系列4:实现客户侧商品列表、商品详情页程序
- RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2->新增记录SQL执行过程
- C#.NET 大型通用信息化系统集成快速开发平台 4.0 版本 - 标准省市县数据的公司选择窗口实现
- WinForm"搜索提示效果(不错的)实现" 之 配餐系统的开发
- SQL 使用系统存储过程实现的通用分页存储过程
- 如何用Baas快速在腾讯云上开发小程序-系列3 :实现腾讯云COS API调用
- 信息管理系统开发架构 配置实现列表展示分析图形及编辑等 构建信息分析展示平台 C#快速开发架构
- 提供进销存、ERP系统快速开发框架源码 (C#+SQL)
- C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本 - 大数据分页功能改进、数据权限改进
- WinForm"立体饼状图实现(附源码示例)" 之配餐系统的开发
- C#.NET 大型通用信息化系统集成快速开发平台 4.0 版本 - 省市区数据权限的实现效果
- WinForm"立体饼状图实现(附源码示例)" 之配餐系统的开发
- unity3d实现插件快速开发对话系统
- 简单快速开发C\S架构程序用最简单的不分层最快的效率达到功能要求的例子程序FrmCommentAdd 添加评论的功能实现
- 如何快速开发树形列表和分页查询整合的WInform程序界面
- 利用XML配置实现增删改查的.net快速开发架构 简单的构建信息管理系统架构