create  procedure XiaoZhengGe
@sqlstr nvarchar(4000), --查询字符串
@currentpage int, --第N页
@pagesize int --每页行数
as
set nocount on
declare @P1 int, --P1是游标的id
@rowcount int
exec sp_cursoropen @P1 output,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcount output
select ceiling(1.0*@rowcount/@pagesize) as 总页数--,@rowcount as 总行数,@currentpage as 当前页
set @currentpage=(@currentpage-1)*@pagesize+1
exec sp_cursorfetch @P1,16,@currentpage,@pagesize 
exec sp_cursorclose @P1
set nocount off测试: XiaoZhengGe '任何条件的SQL语句',2,10

解决方案 »

  1.   

    to:loneghost(菜菜) 
        不要说游标不好,要看在什么情况下,如何取数据的思路,你不妨试试在几百万甚至更多的数据记录下,用它试试看速度的快慢,和你以前的分页存储过程比较一下!
      

  2.   

    不会吧: ( 
    to:lihonggen0(李洪根,MS MVP,标准答案来了)
       我现在所有的DataGrid分页都是用的它,比以前用的那个快,以前的那个在这里:
    SET QUOTED_IDENTIFIER ON 
    GO
    SET ANSI_NULLS ON 
    GO
    --应用举例:Nikko_KF DataGrid_Main.aspx
    --exec DataGrid_Page 'iteminfo',23,1,'id,model_no','',' where id>56 'ALTER         Proc DataGrid_Page
    @QueryStr nvarchar(100), --表名、视图名、查询语句
    @PageSize int=10, --每页的大小(行数)
    @PageCurrent int=1, --要显示的页
    @FdShow nvarchar (1000)='', --要显示的字段列表,如果查询结果有标识字段,需要指定此值,且不包含标识字段
    @FdOrder nvarchar (100)='', --排序字段列表
    @WhereStr nvarchar (200)=''     --内容是' id=3 and model_no like '%24%' and '
    as
    /*--用存储过程实现的分页程序 显示指定表、视图、查询结果的第X页
    对于表中主键或标识列的情况,直接从原表取数查询,其它情况使用临时表的方法
    如果视图或查询结果中有主键,不推荐此方法--李政 2003.10.27--*/
    declare @FdName nvarchar(250) --表中的主键或表、临时表中的标识列名
    ,@Id1 varchar(20),@Id2 varchar(20) --开始和结束的记录号
    ,@Obj_ID int --对象ID
    --表中有复合主键的处理
    declare @strfd nvarchar(2000) --复合主键列表
    ,@strjoin nvarchar(4000) --连接字段
    ,@strwhere nvarchar(2000) --查询条件
    select @Obj_ID=object_id(@QueryStr)
    ,@FdShow=case isnull(@FdShow,'') when '' then ' *' else ' '+@FdShow end
    ,@FdOrder=case isnull(@FdOrder,'') when '' then '' else ' order by '+@FdOrder end
    ,@QueryStr=case when @Obj_ID is not null then ' '+@QueryStr else ' ('+@QueryStr+') a' end--如果显示第一页,可以直接用top来完成
    if @PageCurrent=1
    begin
    select @Id1=cast(@PageSize as varchar(20))
    exec('select top '+@Id1+@FdShow+' from '+@QueryStr+@WhereStr+@FdOrder)
    return
    end--如果是表,则检查表中是否有标识更或主键
    if @Obj_ID is not null and objectproperty(@Obj_ID,'IsTable')=1
    begin
    select @Id1=cast(@PageSize as varchar(20))
    ,@Id2=cast((@PageCurrent-1)*@PageSize as varchar(20)) select @FdName=name from syscolumns where id=@Obj_ID and status=0x80
    if @@rowcount=0 --如果表中无标识列,则检查表中是否有主键
    begin
    if not exists(select 1 from sysobjects where parent_obj=@Obj_ID and xtype='PK')
    goto lbusetemp --如果表中无主键,则用临时表处理 select @FdName=name from syscolumns where id=@Obj_ID and colid in(
    select colid from sysindexkeys where @Obj_ID=id and indid in(
    select indid from sysindexes where @Obj_ID=id and name in(
    select name from sysobjects where xtype='PK' and parent_obj=@Obj_ID
    )))
    if @@rowcount>1 --检查表中的主键是否为复合主键
    begin
    select @strfd='',@strjoin='',@strwhere=''
    select @strfd=@strfd+',['+name+']'
    ,@strjoin=@strjoin+' and a.['+name+']=b.['+name+']'
    ,@strwhere=@strwhere+' and b.['+name+'] is null'
    from syscolumns where id=@Obj_ID and colid in(
    select colid from sysindexkeys where @Obj_ID=id and indid in(
    select indid from sysindexes where @Obj_ID=id and name in(
    select name from sysobjects where xtype='PK' and parent_obj=@Obj_ID
    )))
    select @strfd=substring(@strfd,2,2000)
    ,@strjoin=substring(@strjoin,5,4000)
    ,@strwhere=substring(@strwhere,5,4000)
    goto lbusepk
    end
    end
    end
    else
    goto lbusetemp/*--使用标识列或主键为单一字段的处理方法--*/
    lbuseidentity:
            if len(@WhereStr)>10
    begin
    exec('select top '+@Id1+@FdShow+' from '+@QueryStr
    +@WhereStr+' and '+@FdName+' not in(select top '
    +@Id2+' '+@FdName+' from '+@QueryStr+@WhereStr+@FdOrder
    +')'+@FdOrder
    )
    return
    end
    else
    begin
    exec('select top '+@Id1+@FdShow+' from '+@QueryStr
    +' where '+@FdName+' not in(select top '
    +@Id2+' '+@FdName+' from '+@QueryStr+@FdOrder
    +')'+@FdOrder
    )
    return
    end/*--表中有复合主键的处理方法--*/
    lbusepk:
    exec('select '+@FdShow+' from(select top '+@Id1+' a.* from
    (select top 100 percent * from '+@QueryStr+@FdOrder+') a
    left join (select top '+@Id2+' '+@strfd+' 
    from '+@QueryStr+@FdOrder+') b on '+@strjoin+'
    where '+@strwhere+') a'
    )
    return
    /*--用临时表处理的方法--*/
    lbusetemp:
    select @FdName='[ID_'+cast(newid() as varchar(40))+']'
    ,@Id1=cast(@PageSize*(@PageCurrent-1) as varchar(20))
    ,@Id2=cast(@PageSize*@PageCurrent-1 as varchar(20))exec('select '+@FdName+'=identity(int,0,1),'+@FdShow+'
    into #tb from'+@QueryStr+@FdOrder+'
    select '+@FdShow+' from #tb where '+@FdName+' between '
    +@Id1+' and '+@Id2
    )
    GO
    SET QUOTED_IDENTIFIER OFF 
    GO
    SET ANSI_NULLS ON 
    GO
      

  3.   

    假若你用几十万行数据,你可以看看.你的存储过程还比不上NOT IN分页,示例:
    SELECT Top 10 * FROM Customers WHERE Customerid NOT IN (SELECT TOP 20 Customerid from Customers )declare @SQLStr varchar(8000)
    set @SQLStr='SELECT Top '+cast(@每页大小 as varchar)+' * FROM 表 WHERE 主键列 NOT IN (SELECT TOP '+cast(@每页大小*@第几页 as varchar)+' 主键列 from 表 )'
    exec(@SQLStr)我个人认为最好的分页方法是:
    Select top 10 * from table where id>200
    写成存储过程,上面的语句要拼一下sql语句,要获得最后大于的哪一个ID号 
      

  4.   

    to  XiaoZhengGe:那个用游标的方式,只适合于小数据量的表,如果表在一万行以上,就差劲了
      

  5.   

    lihonggen0(李洪根,MS MVP,标准答案来了) 的确实不错!
     郁闷:我们公司的好多数据表竟然没有主键列!
      

  6.   

    你可以在SQL 查询分析器,看一下执行时间.显示执行计划,显示服务器跟踪统计,显示客户统计以下是我用存储过程分页的方式,分页一个20万行的表,结果显示在网页中,你可以看一下速度:http://www.bizlands.com/trade/search.asp?type=s&sortid=15http://www.yibiz.com/trade/search.asp?sortid=5&type=供应&page=3&country=&sf=&cs=&txtitle=&DateTime=http://www.yibiz.com/trade/search.asp?sortid=7&type=供应
      

  7.   

    对不起大家了!我写的目录主要是通用:因为我的任务中将foxpro2.6中的数据放到网上来查询.
    先是运行存储过程insert to mssql表中,然后分页显示出来.速度还真是蛮快的.不过真的能满足任何表,没有id号和主键的表都行.分页很方便!
      

  8.   

    必须有主键,
    聚集索引速度才快select 的时候,尽量不用select *,只查询你需要的列
      

  9.   

    正如 lihonggen0(李洪根,MS MVP,标准答案来了) 所说,速度还是比较慢!
    http://www.yibiz.com/trade/search.asp?sortid=5&type=供应&page=3&country=&sf=&cs=&txtitle=&DateTime= 这里的分页速度确实是快!配服!
      

  10.   

    呵呵,上面的页面还查询过几个表,用了几个Rs,因为有需求在asp.net中,超过一万行的数据,不建议用Datagrid自带的分页方式,我一般自己写sp
      

  11.   

    更改主键的聚集索引=============>>>>>>>>>>企业管理器中——》设计表——》属性——》索引/键——》选择主键——》将创建为clusted去掉
      

  12.   

    to:楼上的
       我的这个存储过程确实非常的通用,任何表者行,语句也可以任意写,只要符合sql语句规范!数据量不大时建立采用!
      

  13.   

    很久前,我说过用sql的游标游标是存放在内存中,很费内存.游标一建立,就将相关的记录锁住,直到取消游标游标提供了对特定集合中逐行扫描的手段,一般使用游标来逐行遍历数据,根据取出数据条件的不同进行不同的操作。而对于多表和大表中定义的游标(大的数据集合)循环很容易使程序进入一个漫长的等待甚至死机.所以说,我个人的经验,就是一万上行上的表,不用游标.小数据量的表,适当的时候可以用游标因为游标,遍历小数据量的行集还是不错的一个方法!
      

  14.   

    to : penning(我在身边) 用临时表自定义分页和使用游标自定义分页都不好!我个人认为最好的分页方法是:
    Select top 10 * from table where id>200
    写成存储过程,上面的语句要拼一下sql语句,要获得最后大于的哪一个ID号 
      

  15.   

    我觉得有人说得很清楚了。
    用Select top 10 * from table where C1>@value Order by C1
    @value 值取上一页的最后一条记录C1值
      

  16.   

    当然写存储过程要看表的结构!假如你有一个表都一个ID号递增间隔为1
    那么这样的表写存储过程就太方便了.select 字段列表 from 表名 where id>=(页数-1)*页宽+1 and id<=页数*页宽
      

  17.   

    to lihonggen0(李洪根,MS MVP,标准答案来了) ( ) 据我以前测试 从sqlserver板盗版过来的这个方法还是不错的!
    几万的数据还是用不到一秒!
    我用select top 要花26妙再说了要是没有id怎么办
      

  18.   

    可能我还没研究到家!HOHO!~~~
      

  19.   

    @rowcount 是SQL自带的吗?否则你的ROWCOUNT怎么得出得。
    不要见笑啊。用了你得代码不够,要看懂!
      

  20.   

    那个很长的存储过程是邹建写的.好处是非常通用
    但是通用的效率一般不好用select top 要花26秒? 你top多少条数据,有主键吗?
    如果你有主键,top 10 到 20,用了不那么长时间,各位可以用十几万行的表试一下.---------------------------------------没有ID,只能用临时表,但效率不高
      

  21.   

    凑个热闹,我用的,是借了CSDN一个兄弟的,在其基础上改进的CREATE PROCEDURE GetRecordFromPage
        @tblName      varchar(255),       -- 表名
        @fldName      varchar(255),       -- 字段名
        @PageSize     int = 10,           -- 页尺寸
        @PageIndex    int = 1,            -- 页码
        @IsCount      bit = 0,            -- 返回记录总数, 非 0 值则返回
        @OrderType    bit = 0,            -- 设置排序类型, 非 0 值则降序
        @strWhere     varchar(1000) = ''  -- 查询条件 (注意: 不要加 where)
    ASdeclare  @strSQL   varchar(2000)     -- 主语句
    declare @strTmp   varchar(1000)     -- 临时变量
    declare @strOrder varchar(1000)       -- 排序类型if @OrderType != 0
    begin
        set @strTmp = "<(select min"
        set @strOrder = " order by [" + @fldName +"] desc"
    end
    else
    begin
        set @strTmp = ">(select max"
        set @strOrder = " order by [" + @fldName +"] asc"
    endset @strSQL = "select top " + str(@PageSize) + " * from ["
        + @tblName + "] where [" + @fldName + "]" + @strTmp + "(["
        + @fldName + "]) from (select top " + str((@PageIndex-1)*@PageSize) + " ["
        + @fldName + "] from [" + @tblName + "]" + @strOrder + ") as tblTmp)"
        + @strOrderif @strWhere != ''
        set @strSQL = "select top " + str(@PageSize) + " * from ["
            + @tblName + "] where [" + @fldName + "]" + @strTmp + "(["
            + @fldName + "]) from (select top " + str((@PageIndex-1)*@PageSize) + " ["
            + @fldName + "] from [" + @tblName + "] where (" + @strWhere + ") "
            + @strOrder + ") as tblTmp) and (" + @strWhere + ") " + @strOrderif @PageIndex = 1
    begin
        set @strTmp = ""
        if @strWhere != ''
            set @strTmp = " where (" + @strWhere + ")"    set @strSQL = "select top " + str(@PageSize) + " * from ["
            + @tblName + "]" + @strTmp + " " + @strOrder
    endif @IsCount != 0
        set @strSQL = "select count(*) as Total from [" + @tblName + "]"exec (@strSQL)
    GO要注意看,修改后的存储过程在使用@strWhere时,都在其前后加上了(),这样,就防止嵌套的()出现错误下面的代码是引用该存储过程的一个范例 SqlConnection MyConnection=new SqlConnection(ConfigurationSettings.AppSettings["dsn"]);
    DataSet MyDataSet=new DataSet();
    string strKeyword=Keyword.Text.Trim().Replace("\'","\'\'");
    string strSalesId=Sales.SelectedItem.Value;
    int RecordCount=CalcRecordCount();
    RecordNumber.Text=RecordCount.ToString();
    LblRecordNumber.Text=RecordCount.ToString();
    string strExpress="Id<>0";
    if (strKeyword!="")
    strExpress=strExpress+" and (companyenname like '%"+strKeyword+"%' or companychname like '%"+strKeyword+"%' or Companyshortname like '%"+strKeyword+"%' or web like '%"+strKeyword+"%' or mainproduct like '%"+strKeyword+"%' or phone like '%"+strKeyword+"%' or memo like '%"+strKeyword+"%' or address like '%"+strKeyword+"%' or linkmanphone like '%"+strKeyword+"%')";
    if (strSalesId!="")
    strExpress=strExpress+" and salesid="+strSalesId;
    SqlCommand MyCommand=new SqlCommand();
    MyCommand.Connection=MyConnection;
    MyCommand.CommandText="GetRecordFromPage";
    MyCommand.CommandType=CommandType.StoredProcedure;
    MyCommand.Parameters.Add("@tblName","customerview");
    MyCommand.Parameters.Add("@fldName","id");
    MyCommand.Parameters.Add("@strWhere",strExpress);
    MyCommand.Parameters.Add("@PageSize",Int32.Parse(CustomerList.PageSize.ToString()));
    MyCommand.Parameters.Add("@PageIndex",Int32.Parse(ViewState["PageIndex"].ToString())+1);
    SqlDataReader MyReader;
    MyConnection.Open();
    MyReader=MyCommand.ExecuteReader();
    CustomerList.VirtualItemCount=RecordCount;
    CustomerList.DataSource=MyReader;
    CustomerList.DataKeyField="id";
    CustomerList.DataBind();
    MyReader.Close();
    MyConnection.Close();在这里,要注意的是存储过程使用的PAGEINDEX变量是从1开始就算条件再复杂,也能搞定
      

  22.   

    关于存储过程的分页,SQL Server版讨论过很多次了.大家可以搜索一下
    然后再发表自己的意见
      

  23.   

    XiaoZhengGe 发的那个存储过程最早是出自j9988之手,我测试过小数据量还可以,但效率是确不好
    好处是通用
      

  24.   

    to  test7979:看看csdn的论坛,就是有主键ID
    这样的应用很多一个表中,你不会没有主键,索引吧.如果没有查询会更慢如果主键不是数字,是字符,可用临时表报表都有非常复杂的排序,在SQL上体现无非就是order by 
      

  25.   

    to lihonggen0表是有主键,但绝大部分报表都不会这么简单的,绝大部分时候都用不上主键,当然排序还是需要的而且像这么分页,我如果要作小计,或者合计,这种做法根本没法做,可以这么说,绝大部分的报表都是无法通过这种简单的SQL查询就能得到的,或许大家碰到的报表都是太简单了,像CSDN那样的只是特列
      

  26.   

    lihonggen0(李洪根,MS MVP,标准答案来了) 一般id都有索引
    要是我按某一列排序或某几列,
    然后怎么个 select top . id 都乱了啊!难道另外在select的时候 另外弄出个替增id出来?
      

  27.   

    to  xinyulou:ID 列当然可以不连续呀!
    排序也是可以的!用Select top 10 * from table where C1>@value Order by C1
    @value 值取上一页的最后一条记录C1值如;
    Select top 10 * from orders where orderid<11074 Order by orderid desc
      

  28.   

    to  test7979(test7979) :你说做报表,作小计,或者合计,我的处理是一般在前台处理,比如在水晶报表,
    或者是Report Service 里,很容易就可以!如果写在存储过程里,也是可以的,但是不是我推荐的方法!
      

  29.   

    to lihonggen0但是如果像这样分页,就无法作小计和合计了,因为你不知道前面的数据
      

  30.   

    如果数据量不是很大,用我这个方法加分页控件速度很快的,我测试过,十几万条数据分页,每页显示10条,前几百页分页用时不超过一秒:http://www.webdiyer.com
      

  31.   

    heroman1979(网络虫子) 
    提供的那个存储过程,我看已经相当好了
    速度快不快,要看你
    select top n * from 表
    那个n的值到底多大,就是取决于你的PageSize
      

  32.   

    李老大说上面的都不快他的意见是
    Select top 10 * from table where id>200
    写成存储过程,上面的语句要拼一下sql语句,要获得最后大于的哪一个ID号 
    我看这个方法,不就是邹建的那个很长的存储过程?核心不也是它
      

  33.   

    CURSOR or NOT CURSOR  ??? 具体问题要具体分析。
      

  34.   

    先顶一下
    经典的程序,非常的通用和使用。多谢搂主。另外我也是比较关注在大数据量的情况下的结果,所以简单测试了一下(仅供参考),2CPU,512M memory,sqlserver 2000, 
    小数据量(<1W)的情况下, <1秒
    40W数据量,top1000,page30,size15: Result: >20秒
    160W数据量  >1分钟
      

  35.   

    SELECT * FROM Products order by ProductName
    SELECT TOP 10 * FROM Products where ProductName>'Chang' order by ProductName不一定要按照ID来吧
      

  36.   

    确实快……不过呢,该扔到SQL版去——对于.net应该用.net的方法么……
    比如这个
           PagedDataSource pds = new PagedDataSource();
           pds.DataSource = data.Tables[0].DefaultView; // 某 ADO.net DataView
           pds.AllowPaging = true;
           pds.PageSize = 10; // 大小
           pds.CurrentPageIndex = (Request.QueryString["Page"] == null) ? 0 : Int32.Parse(Request.QueryString["Page"]); // 现在的页号
    然后用
           binder.DataSource = pds;
           binder.DataBind();
    就可以绑喽如果内存足够多尤其是IA的EBA模式的话,速度比你那个存储过程要快(注意:前提是内存足够!比如10G啦——理论上讲可以处理一万行每行1k的数据)
      

  37.   

    to:  lihonggen0(李洪根,MS MVP,标准答案来了) select top 问题还是很严重比如 select col1 , col2 from table1  order by col1 disc,col2,col3 disc而且排序的字段有不清楚了
    比如:用户点 col1然后按col1排序显示,然后用户在点一下col2 按col1,col2排序头是不是要大了!不可能用id>常量
    因为在当前页里 肯定会有id比常量小的行!这个常量也就是上页的最后一行的id号这个常量不一定比当前页中的id号都大或都小,因此不能用id来比较除非有自动产生一个有顺序的id号,好像是不现实的
      

  38.   

    sql server要能提供@row变量就好办多了
    id>2000这种形式速度是快,可是2000这个数字还是要计算的,要么用临时表,要么用NOT in
      

  39.   

    to XiaoZhengGe (㊣小政哥㊣·www.yueyan.com·㊣小政哥㊣) 
    你的这个效率真的是很差的.其实一句就搞定了,你写了那么多做什么
      

  40.   

    前段时间做了个数据分析系统,采用asp.net+sqlserver 2000。由于数据量实时采集,平均每秒钟有2-3条数据插入。客户工作日期间利用系统对数据进行相关分析。在建表时的考虑,由于数据量大,最新数据放在history表中。经过手工处理后的部分数据或者根据条件自动处理后的数据(自动处理的数据大约占所有数据的3/4左右。剩下的需要手工处理或者不处理。)放于对应月份的表中,如现在就放在back_8表中。每月份的备份数据即back表数据保存一年时间。现在就是建索引问题,性能优化问题。目前分析系统几乎不可用,每次分析都要好几分钟才能出来。一般跨月查询比较少,查询条件基本上不跨月。即用户选择的开始时间和结束时间均在同一月份。跨月查询的效率暂不考虑,因为用户用得少。但是不跨月也要查两张表,一张是history表,一张是back_当前月表。因为后面一张表名不确定,所以存储过程中很多使用了动态查询语句,这样才能传表名。两张表另外查询,然后用union合并记录。另外一个就是时间处理上,字段date_time类型为datetime。用户要求有按照用户选择的开始时间到结束时间中的全部时间、这段时间的周末时间、这段时间的工作日时间查询。还有一个就是site_name字段,该查询条件的参数也是一个列表,即用户要求在界面中能多选site_name。所有分析用得最多的条件就是上面两个。目前我用date_time + site_name建了个聚集索引。速度快了一些,约5/1左右,测试数据库数据量100万条。但是还是不行,还很慢。是不是site_name也使用in查询导致速度慢?但是site_name列表不定,而且可能上百个上千个。所以非常不好优化。目前没有思路。哪位高手有好的办法?如何提高in的效率?或者有没有别的办法代替in(sitename列表)?
      

  41.   

    凑个热闹,数据记录上万的时候,使用临时表比使用组合select语句要快的多,大家可以测试:
    /*
    aothor wuchen
    date   2003/11/25
    name   NewsItemList
    descreption:
           新闻分页显示,可通过TypeId来指定选择新闻的类型,不指定则全部显示
    */CREATE PROCEDURE dbo.NewsItemList (
    @PageIndex  int ,  --索引页码号
        @PageSize int,     --每页记录数
        @TypeId   int=0    --新闻类型id  
    )AS
        DECLARE @PageLowerBound int
            DECLARE @PageUpperBound int

    -- Set the page bound
    SET @PageLowerBound = @PageSize * @PageIndex
    SET @PageUpperBound = @PageLowerBound + @PageSize + 1
        
    -- Create a temp Table to store the select results
    CREATE TABLE #PageIndexFornewslist (
    IndexId int IDENTITY(1,1) NOT NULL ,
    newsId int 
    )
        
         -- Insert into #PageIndexFornewslist
         if @TypeId = 0
         BEGIN
     INSERT INTO #PageIndexFornewslist(newsId) 
          SELECT n.ID FROM newslist as n
          ORDER BY n.CreateDate DESC
    END
    else
    BEGIN
     INSERT INTO #PageIndexFornewslist(newsId) 
          SELECT n.ID FROM newslist as n 
          where n.typeid=@TypeId      
          ORDER BY n.CreateDate DESC
    END 
    -- select  record
    if @TypeId = 0 
    BEGIN
    select 
    n.ID,
    n.Subject,
    n.CreateDate,
    n.Content,
    n.Author,
    n.click,
    n.img,
    n.typeid,
    (DateDiff(day,ISNULL(n.CreateDate,0),getdate())) AS diffday 
    from 
    newslist n (nolock),
    #PageIndexFornewslist AS t
    where
    n.ID = t.newsId            and 
    t.IndexId >@PageLowerBound and
    t.IndexId<@PageUpperBound
    order by t.IndexId
        END
        else
        begin
    select 
    n.ID,
    n.Subject,
    n.CreateDate,
    n.Content,
    n.Author,
    n.click,
    n.img,
    n.typeid ,
    (DateDiff(day,ISNULL(n.CreateDate,0),getdate())) AS diffday 
    from 
    newslist n (nolock),
    #PageIndexFornewslist AS t
    where
    n.ID = t.newsId            and 
    n.typeid=@TypeId           and
    t.IndexId >@PageLowerBound and
    t.IndexId<@PageUpperBound
    order by t.IndexId 
        
       end



      

  42.   

    我不是说过嘛,不同的需求,做法就不一样!not in 方法,和select top 的方法我是测试过的,比如分页一个20万行的表结果:
    http://www.bizlands.com/trade/search.asp?type=s&sortid=15
    http://www.bizlands.com/trade/search.asp?type=s&sortid=14象这种需求,我是不用临时表和游标的.根据我的测试NOT IN的性能不如select top的方式,在我的测试环境中是这样.两年前为了这个问题,我还提交了一份10页的报告(因为表中可能会上百万行).如果要考虑到多个字段的排序.我会用not in的方式,写一个通用的存储过程.实在达不到需求的时候,才考虑用临时表.游标一般是最后考虑的.(因为用临时表的方法,可以代替游标.)
      

  43.   

    分页代码不写一百行以上,效率很难高到哪去
    还有就是SQL语句里尽量不要用not in,这样效率很低
      

  44.   


    to  xinyulou:你可以看一下:
    http://www.bizlands.com/trade/search.asp?type=s&sortid=15这个ID就是不连续的
      

  45.   

    大家要用SQL 查询分析器,看一下执行时间.显示执行计划,显示服务器跟踪统计,显示客户统计
    这样才能看出来!
      

  46.   

    select top 的方式确实很好,学习
      

  47.   

    现在问题是像我这样的需求,select ××× from table
    where datetime>=starttime and datetime<=endtime and sitename in("name1","name2",
    "name3")
    in里面的列表是不定的,由用户选择的。这样写又没有办法用到索引。不知道如何取舍,大家能不能帮我想个办法啊?还有就是这种情况,索引如何建立?
      

  48.   

    goodluck001(Endeavoring) 你这个想法倒是不错,但具体的双怎么实施的?
      

  49.   

    CREATE   procedure up_DataPagging2
    @operation int, --操作類型,0為取得當前頁記錄集,1為取得記錄總數(RecordCount)
    @TableName varchar(100), --要操作的表名
    @FieldLists varchar(8000), --字段列表,可以為'*",也可為空
    @KeyField varchar(100), --關鍵字段名
    @Critical varchar(200), --查詢條件
    @SortType varchar(4), --排序類型,為'DESC'或者'ASC',為空是默認為'ASC'
    @PageSize int, --每頁大小,大於0的整數
    @ShowPageNo int --當前要顯示的頁碼,大於0的整數,頁數從1開始
    AS
    declare @SelectSqlString varchar(8000),@tempSql varchar(8000)
    if @operation=0
    begin
    --要返回的記錄
    select @SelectSqlString='SELECT TOP '+STR(@PageSize)
    if rtrim(@FieldLists)=''
    select @FieldLists='*' select @SelectSqlString=@SelectSqlString+' '+@FieldLists+' from '+@TableName if rtrim(@SortType)='ASC'
    select @tempSql='>(select max(Out.'
    else
    select @tempSql='<(select min(Out.' select @tempSql=@tempSql+@KeyField+') from (select top '+str(@PageSize*(@ShowPageNo-1))+' '+@KeyField+'  from '+@TableName if rtrim(@Critical)!=''
    select @tempSql=@tempSql+' where '+@Critical if upper(rtrim(@SortType))!='DESC'
    select @SortType='ASC' select @tempSql=@tempSql+' order by '+@KeyField+' '+@SortType+') as Out) '
    if rtrim(@Critical)!=''
    begin
    select @Critical=' where '+@Critical
    if @ShowPageNo>1
    select @Critical=@Critical+' and '+@KeyField+@tempSql
    end
    else
    if @ShowPageNo>1
    select @Critical=' where '+@KeyField+@tempSql select @SelectSqlString=@selectSqlString+@Critical+' order by '+@KeyField+' '+@SortType execute(@SelectSqlString)
    --select @SelectSqlString as sqlstr
    end else begin
    select @SelectSqlString='select count(*) as RecordCount from '+@TableName
    if rtrim(@Critical)!=''
    select @SelectSqlString=@SelectSqlString+' where '+@Critical
     execute(@SelectSqlString)
    end
    GO