在你的SQL语句里,加一段
order by 价钱

order by 面积你分页时要用session变量或加在URL里的办法记住用户的选择

解决方案 »

  1.   


    一. 引言 
     
    贵刊今年10月10日东北大学张春明和姜绍飞的"Web数据库记录分页技术与实现"一文介绍了利用微软RecordSet组件对象实现数据库记录分页. 该方法虽然有其可取之处, 但也有不足之处. 
     
    首先该方法将所有查询结果保存到一个RecordSet对象中, 然后利用RecordSet对象的几个特殊属性把数据库记录划分成不同的页面. 这样在同一查询Session的不同页面之间, 要么保存该RecordSet对象于Session中, 要么每次都进行查询以得到RecordSet对象. 其缺点是很明显的, 不仅浪费资源, 而且缺乏效率. 
     
    该方法的另外一个明显缺点是缺乏可移植性, 如很难移植到J2EE应用中. 因为它过于依赖微软RecordSet组件对象固有的特性以实现分页的目的.  
     
    大家知道, WEB应用中数据库连接资源是很昂贵的, 因此, 有必要探索一种有效的记录分页算法,同时兼顾到移植性. 
     
    二. 基于SQL分页算法 
     
    我们知道, SQL 是一种功能性非常强的数据库编程语言, 同时它也是一个工业标准. 因此, 如果我们能够演绎出一套基于 SQL 的有效分页算法, 那么也就兼顾了算法的可移植性. 本文将要介绍的正是这样一种分页算法.  
     
    1. 假设 records_per_page 包含每页记录数 
     
    2. 查询总记录数并计算总页数  
     
    (1) 查询总记录数 total_records 
     
    select count(*) from your-table-list  
    where your-criteria 
     
    (2) 计算总页数 total_pages 
     
    total_pages = (total_records + records_per_page - 1) 
    / records_per_page 
     
    3. 假设 current_page 包含当前页号 
     
    则其约束区间为 [1, total_pages] 
     
    4. 计算未显示记录数 not_shown_records 
     
    not_shown_records = total_records -  
    (current_page - 1) * records_per_page 
     
    5. 查询当前页所有记录 
     
    select top records_per_page * 
    from ( 
    select top not_shown_records * 
    from your-table-list 
    where your-criteria 
    order by your-sort-field desc 
    ) a 
    order by a.your-sort-field asc 
     
    注意: your-sort-field 包含了一个排序字段. 你可以指定 
    多个排序字段, 但是必须保证里外包含相同的排序字段. 
    外层的每个排序字段前加上"a." 
     
    该算法在同一查询Session中, 只需要查询总记录数并计算总页数一次. 然后, 在不同页面之间传递总记录数和总页数. 每次只查询当前页所需记录. 这样不仅节省了连接资源, 而且效率也高, 同时兼顾了移植性. 你不仅可以在微软ASP中使用该分页算法, 也可以在SUN J2EE平台上轻松实现, 你甚至可以在CGI/PERL中使用该技术. 
     
    三. 实现示例 
     
    下面的程序示例使用了微软ASP技术和SQL7.0 Northwind数据库中的Orders表来演示如何实现这一分页算法.这是一个完整的经测试过的程序. 由于程序注释很详细, 这里就不再赘述. 
     
    <%@ Language=JavaScript%> 
    <% 
    //------------------------------------------------------------- 
    // dbpaging.asp 
    //------------------------------------------------------------- 
    Response.Expires = -1; 
     
    // 定义变量 
    var nRecordsPerPage, nTotalRecords, nTotalPages, nCurrentPage, nNotShownRecords; 
    var nFirstPage, nPrevPage, nNextPage, nLastPage; 
    var szConnection, oConnection, oRecordset, szSql; 
    var szShowPageUrl; 
     
    // 查询同一查询Session不同页面之间传递参数 
    nTotalRecords = parseInt(Request.QueryString("totalrecords")); 
    nTotalPages = parseInt(Request.QueryString("totalpages")); 
    nCurrentPage = parseInt(Request.QueryString("showpage")); 
     
    // 设置每页显示记录数 
    nRecordsPerPage = 10; 
     
    // ODBC连接参数: 使用你自己的DSN,帐号以及密码 
    // 这里Northwind应指向微软SQL7.0 Northwind示例数据库 
    szConnection = "DSN=Northwind;UID=test;PWD=;"; 
    oConnection = Server.CreateObject("ADODB.Connection"); 
    oConnection.Open(szConnection); 
     
    // 检测是否首次进入该查询Session 
    if (isNaN(nCurrentPage)) { 
    // 是, 设置第一页为当前页, 查询总记录数并计算总页数  
    nCurrentPage = 1; 
    szSql = "select count(*) from Orders"; 
    oRecordset = oConnection.Execute(szSql); 
    nTotalRecords = oRecordset(0).value; 
    oRecordset.Close(); 
    oRecordset = null; 
     
    nTotalPages = parseInt((nTotalRecords + nRecordsPerPage - 1) / nRecordsPerPage); 

     
    // 设置页面切换参数 
    nFirstPage = 1; // 首页 
    nPrevPage = nCurrentPage - 1; // 前一页 
    nNextPage = nCurrentPage + 1; // 下一页 
    nLastPage = nTotalPages; // 最后页 
    if (nPrevPage < 1) nPrevPage = 0; 
    if (nNextPage > nTotalPages) nNextPage = 0; 
     
    // 计算未显示记录数 
    nNotShownRecords = nTotalRecords - (nCurrentPage - 1) * nRecordsPerPage;  
     
    // 查询当前页所有记录 
    szSql = "select top " + nRecordsPerPage + " * " +  
    "from ( " +  
    "select top " + nNotShownRecords + " OrderID, CustomerID, " +  
    "ShipName, ShipAddress, ShipCity, ShipPostalCode, ShipCountry " +  
    "from Orders " +  
    "order by OrderID desc " +  
    ") a " +  
    "order by a.OrderID asc"; 
    oRecordset = oConnection.Execute(szSql); 
    %> 
     
    <html><head><title>DB Paging Demo</title></head><body><center> 
    <% 
    // 显示当前页所有记录 
    if (!oRecordset.EOF) { 
    %><table cellpadding="2" cellspacing="0" border="1" width="800"><tr> 
    <td align="center"><b>Order ID</b></td> 
    <td align="center"><b>Customer ID</b></td> 
    <td align="center"><b>Ship Name</b></td> 
    <td align="center"><b>Ship Address</b></td> 
    <td align="center"><b>Ship City</b></td> 
    <td align="center"><b>Ship Postal Code</b></td> 
    <td align="center"><b>Ship Country</b></td> 
    </tr> 
    <%  
    oRecordset.MoveFirst(); 
    while(!oRecordset.EOF) { 
    %><tr> 
    <td align="center"><%=oRecordset("OrderID").value%></td> 
    <td align="left"><%=oRecordset("CustomerID").value%></td> 
    <td align="left"><%=oRecordset("ShipName").value%></td> 
    <td align="left"><%=oRecordset("ShipAddress").value%></td> 
    <td align="left"><%=oRecordset("ShipCity").value%></td> 
    <td align="left"><%=oRecordset("ShipPostalCode").value%></td> 
    <td align="left"><%=oRecordset("ShipCountry").value%></td> 
    </tr>  
    <% 
    oRecordset.MoveNext(); 

    %></table><% 

    oRecordset.Close(); 
    oRecordset = null; 
     
    // 设置页面切换链接参数 
    szShowPageUrl = "dbpaging.asp?totalrecords=" + nTotalRecords 
    + "&totalpages=" + nTotalPages + "&showpage="; 
     
    %><table cellpadding="2" cellspacing="0" border="0" width="600"><tr> 
    <td align="center"> </td> 
    <td align="center"> <b><%  
    // 显示首页链接 
    if (nPrevPage > 0) { 
    %><p><a href="<%=szShowPageUrl%><%=nFirstPage%>">First</a><% 

    %></b></td> 
    <td align="center"> <b><%  
    // 显示前一页链接 
    if (nPrevPage > 0) { 
    %><p><a href="<%=szShowPageUrl%><%=nPrevPage%>">Previous</a><% 

    %></b></td> 
    <td align="center"> </td> 
    <td align="center"> <b><%  
    // 显示下一页链接 
    if (nNextPage > 0 ) { 
    %><p><a href="<%=szShowPageUrl%><%=nNextPage%>">Next</a><% 

    %></b></td> 
    <td align="center"> <b><%  
    // 显示最后页链接 
    if (nNextPage > 0 ) { 
    %><p><a href="<%=szShowPageUrl%><%=nLastPage%>">Last</a><% 

    %></b></td> 
    <td align="center"> </td> 
    </tr></table> 
    </center></body></html> 
     
    四. 结论 
     
    由于WEB应用本身的局限性以及平台的多样性, 这就要求我们在后台处理时应当对技术和算法进行慎重考虑, 不仅要考虑其可实现性, 而且更应该注意其效率和可移植性. 对于WEB应用来讲数据库记录分页是一个常见的要求, 本文给出了一个常用的基于SQL的行之有效的分页算法. 不足之处, 恭请方家指正. 
     
      

  2.   

    to: hope2002(乐于助人)在下就不客气了,给出几个不足如下,抛砖引玉吧:
    1.上述,写在Session对象的思路虽然可以节省些资源,但是即时性就要受到影响。如果有用户对数据库进行大的修改,则不能保证程序正确。这个对于Web程序好像问题不大,但最好能够让这个Session对象定时更新
    2.上述查询总记录数 total_records 的方法也有待改进。
    select count(*) from your-table-list  where your-criteria 
    通常一个页面显示的数据都是一个复杂的查询结果;使用count(*)似乎不能简单的描述,如何改进呢?
      

  3.   

    说得可是容易,你写来试试,直接用cout(子表.*)在SQLServer下是不行的,必须指定特定的字段;