本来只显示100条记录应该是很快的,但是实际运行速度却很慢,我估计是把所有的记录全给返回了,然后再挑出100条来显示。不知道有什么方法可以获取从给定的位置开始给定数目的记录,并且系统开销很小。
不要告诉我用主键ID, 因为排序不一定是按照主键来的。实际上除了主键也没有其他的索引(因为重复率很高)。
16 个解决方案
#1
>>>>但是实际运行速度却很慢
把你的SQL语句贴出来, 或这么做
如果你排序的话,第一次用
select top 100 * from yourtable order by SomeField
记住每页的第一个和最后一个记录
往后翻页,你用
select top 100 * from yourtable where SomeField > '最后一个记录' order by
SomeField
往前翻页,你用
select * from (select top 100 * from yourtable where SomeField < '第一个
记录' order by SomeField desc ) t order by SomeField
>>>>不要告诉我用主键ID, 因为排序不一定是按照主键来的。实际上除了主键也没有其他的>>>>索引
速度慢冤不得人, 祝你好运!
把你的SQL语句贴出来, 或这么做
如果你排序的话,第一次用
select top 100 * from yourtable order by SomeField
记住每页的第一个和最后一个记录
往后翻页,你用
select top 100 * from yourtable where SomeField > '最后一个记录' order by
SomeField
往前翻页,你用
select * from (select top 100 * from yourtable where SomeField < '第一个
记录' order by SomeField desc ) t order by SomeField
>>>>不要告诉我用主键ID, 因为排序不一定是按照主键来的。实际上除了主键也没有其他的>>>>索引
速度慢冤不得人, 祝你好运!
#2
一般的方法
select Top pageSize *
from T
where SortField NOT IN (select Top pageSize*pagei SortField
from T
order by SortField )
order by SortField
例如,每页7条,列印第7页:
select Top 10 *
from T
where SortField NOT IN (select Top 70 SortField
from T
order by SortField )
order by SortField
or
CREATE PROCEDURE Get_Customers_By_Page
@CurrentPage int,
@PageSize int,
@TotalRecords int output
as
SELECT identity(int,1,1) as id ,* into #TempTable from table
DECLARE @FirstRec int, @LastRec int
SELECT @FirstRec = (@CurrentPage - 1) * @PageSize
SELECT @LastRec = (@CurrentPage * @PageSize + 1)
SELECT
*
FROM
#TempTable
WHERE
ID > @FirstRec
AND
ID < @LastRec
SELECT @TotalRecords = COUNT(*) FROM table
select Top pageSize *
from T
where SortField NOT IN (select Top pageSize*pagei SortField
from T
order by SortField )
order by SortField
例如,每页7条,列印第7页:
select Top 10 *
from T
where SortField NOT IN (select Top 70 SortField
from T
order by SortField )
order by SortField
or
CREATE PROCEDURE Get_Customers_By_Page
@CurrentPage int,
@PageSize int,
@TotalRecords int output
as
SELECT identity(int,1,1) as id ,* into #TempTable from table
DECLARE @FirstRec int, @LastRec int
SELECT @FirstRec = (@CurrentPage - 1) * @PageSize
SELECT @LastRec = (@CurrentPage * @PageSize + 1)
SELECT
*
FROM
#TempTable
WHERE
ID > @FirstRec
AND
ID < @LastRec
SELECT @TotalRecords = COUNT(*) FROM table
#3
create procedure cur_num @num int
as
declare @sql varchar(8000)
set @sql = 'select top '+ cast(@num as varchar(100)) + ' * from 表'
exec(@sql)
as
declare @sql varchar(8000)
set @sql = 'select top '+ cast(@num as varchar(100)) + ' * from 表'
exec(@sql)
#4
修改
create procedure cur_num @num int,@num1
as
declare @sql varchar(8000)
set @sql = 'select top '+ cast(@num as varchar(100)) + ' * from 表 where id >@num1'
exec(@sql)
create procedure cur_num @num int,@num1
as
declare @sql varchar(8000)
set @sql = 'select top '+ cast(@num as varchar(100)) + ' * from 表 where id >@num1'
exec(@sql)
#5
to: happydreamer(黑DD)
你说的意思我明白,我也这样想过,但它的效率直在值得商榷,
比如说我想取得第 500001到500100 的100条记录,那么你的语句就是:
select Top 10 * from T
where SortField NOT IN (select Top 500000 SortField
from T order by SortField )order by SortField
效率很低吧。你的另一种方法也一样,先把这么多记录倒到另一个临时表中,也一定很慢。
to: saucer(思归, MS .NET MVP) :
你说的第一页用 select top 100 * ... 我能理解。但是以后的记录你用下面的语句:
select top 100 * from yourtable where SomeField > '最后一个记录' order by
SomeField
就有一个假设:SomeField 必须是唯一索引。 如果根本就没有索引的话,该怎么办呢。
我想要的其实就是类似 select between 500001 and 500100 * from T 的这样一个语句。但又要顾及到效率。
to wgy2008(北极光) :
你说的也只是显示头一百条时的情况。
你说的意思我明白,我也这样想过,但它的效率直在值得商榷,
比如说我想取得第 500001到500100 的100条记录,那么你的语句就是:
select Top 10 * from T
where SortField NOT IN (select Top 500000 SortField
from T order by SortField )order by SortField
效率很低吧。你的另一种方法也一样,先把这么多记录倒到另一个临时表中,也一定很慢。
to: saucer(思归, MS .NET MVP) :
你说的第一页用 select top 100 * ... 我能理解。但是以后的记录你用下面的语句:
select top 100 * from yourtable where SomeField > '最后一个记录' order by
SomeField
就有一个假设:SomeField 必须是唯一索引。 如果根本就没有索引的话,该怎么办呢。
我想要的其实就是类似 select between 500001 and 500100 * from T 的这样一个语句。但又要顾及到效率。
to wgy2008(北极光) :
你说的也只是显示头一百条时的情况。
#6
SQLServer中分页只能这样了:
exec('SELECT Top '+cast(@每页大小 as varchar)+' * FROM T WHERE SortField NOT IN (SELECT TOP '+cast(@每页大小*@第几页 as varchar)+' SortField from T )')
只有oracle里有rowid速度也很快,期待sqlserver下一个版本有rowid
exec('SELECT Top '+cast(@每页大小 as varchar)+' * FROM T WHERE SortField NOT IN (SELECT TOP '+cast(@每页大小*@第几页 as varchar)+' SortField from T )')
只有oracle里有rowid速度也很快,期待sqlserver下一个版本有rowid
#7
不外乎,利用触发器,在记录变更时重新计算变更记录以后的行号。
#8
唉,看来是没有很好的解决方法了。
以上的解决方法无非有以下几种:
1. 用 select top 100 * from T where .. not in ( select top beginIndex ... ), 但是当 beginIndex 很大的时候,比如 1000000, 这样做无疑效率很低。
2. 利用索引,把每次查询后的索引值记录。但是当索引值重复很大或者根本没有索引时,这种方法就不行了。
3. 用类似 oracle里的rowid, 但是 sql-server 里没有。 :-(
我现在用的是 ado.net 里的 DbDataAdapter.Fill 方法里的功能来实现分页的,但是效率很低,所以想找一种能直接在数据库里实现的方法。
各位大侠帮忙啊
以上的解决方法无非有以下几种:
1. 用 select top 100 * from T where .. not in ( select top beginIndex ... ), 但是当 beginIndex 很大的时候,比如 1000000, 这样做无疑效率很低。
2. 利用索引,把每次查询后的索引值记录。但是当索引值重复很大或者根本没有索引时,这种方法就不行了。
3. 用类似 oracle里的rowid, 但是 sql-server 里没有。 :-(
我现在用的是 ado.net 里的 DbDataAdapter.Fill 方法里的功能来实现分页的,但是效率很低,所以想找一种能直接在数据库里实现的方法。
各位大侠帮忙啊
#9
那些都是“直接在数据库了实现”的方法啊!!!!
只有“ado.net 里的 DbDataAdapter.Fill ”才是在客户端实现的方法。
只有“ado.net 里的 DbDataAdapter.Fill ”才是在客户端实现的方法。
#10
傻了吧叽的ado.net是怎么做的呢?他把100万数据读到客户端,然后只留下需要的一页数据,剩下的再丢弃。
所以,即使你认为“很慢”的查询语句,也比你用ado.net的所谓分页功能要快不知道多少倍。
所以,即使你认为“很慢”的查询语句,也比你用ado.net的所谓分页功能要快不知道多少倍。
#11
这里,之所以慢,不在于服务器上查询中间结果需要的数据的多,而在于要将过多的结果数据在网络上传送到客户端。
#12
楼上说的对!
exec('SELECT Top '+cast(@每页大小 as varchar)+' * FROM T WHERE SortField NOT IN (SELECT TOP '+cast(@每页大小*@第几页 as varchar)+' SortField from T )')
肯定比你ado.net里做的快!
exec('SELECT Top '+cast(@每页大小 as varchar)+' * FROM T WHERE SortField NOT IN (SELECT TOP '+cast(@每页大小*@第几页 as varchar)+' SortField from T )')
肯定比你ado.net里做的快!
#13
SQLServer中分页这样比较好:
exec('SELECT Top '+cast(@每页大小 as varchar)+' * FROM T WHERE SortField NOT IN (SELECT TOP '+cast(@每页大小*@第几页 as varchar)+' SortField from T )')
速度不是很快,但是没有什么问题
exec('SELECT Top '+cast(@每页大小 as varchar)+' * FROM T WHERE SortField NOT IN (SELECT TOP '+cast(@每页大小*@第几页 as varchar)+' SortField from T )')
速度不是很快,但是没有什么问题
#14
谢谢w_rose,你说得对。我回去试一试,星期一再结帐
#15
谢谢 happydreamer(黑DD) 及各位的回答,我试了一下,你们是对的。
本来最好是数据库直接支持,即然可以有 select top N ..., 为什么不可以有类似
select between N1 and N2 ...的语句呢?
数据库直接支持的效率显示是最高的
本来最好是数据库直接支持,即然可以有 select top N ..., 为什么不可以有类似
select between N1 and N2 ...的语句呢?
数据库直接支持的效率显示是最高的
#16
学习中
#1
>>>>但是实际运行速度却很慢
把你的SQL语句贴出来, 或这么做
如果你排序的话,第一次用
select top 100 * from yourtable order by SomeField
记住每页的第一个和最后一个记录
往后翻页,你用
select top 100 * from yourtable where SomeField > '最后一个记录' order by
SomeField
往前翻页,你用
select * from (select top 100 * from yourtable where SomeField < '第一个
记录' order by SomeField desc ) t order by SomeField
>>>>不要告诉我用主键ID, 因为排序不一定是按照主键来的。实际上除了主键也没有其他的>>>>索引
速度慢冤不得人, 祝你好运!
把你的SQL语句贴出来, 或这么做
如果你排序的话,第一次用
select top 100 * from yourtable order by SomeField
记住每页的第一个和最后一个记录
往后翻页,你用
select top 100 * from yourtable where SomeField > '最后一个记录' order by
SomeField
往前翻页,你用
select * from (select top 100 * from yourtable where SomeField < '第一个
记录' order by SomeField desc ) t order by SomeField
>>>>不要告诉我用主键ID, 因为排序不一定是按照主键来的。实际上除了主键也没有其他的>>>>索引
速度慢冤不得人, 祝你好运!
#2
一般的方法
select Top pageSize *
from T
where SortField NOT IN (select Top pageSize*pagei SortField
from T
order by SortField )
order by SortField
例如,每页7条,列印第7页:
select Top 10 *
from T
where SortField NOT IN (select Top 70 SortField
from T
order by SortField )
order by SortField
or
CREATE PROCEDURE Get_Customers_By_Page
@CurrentPage int,
@PageSize int,
@TotalRecords int output
as
SELECT identity(int,1,1) as id ,* into #TempTable from table
DECLARE @FirstRec int, @LastRec int
SELECT @FirstRec = (@CurrentPage - 1) * @PageSize
SELECT @LastRec = (@CurrentPage * @PageSize + 1)
SELECT
*
FROM
#TempTable
WHERE
ID > @FirstRec
AND
ID < @LastRec
SELECT @TotalRecords = COUNT(*) FROM table
select Top pageSize *
from T
where SortField NOT IN (select Top pageSize*pagei SortField
from T
order by SortField )
order by SortField
例如,每页7条,列印第7页:
select Top 10 *
from T
where SortField NOT IN (select Top 70 SortField
from T
order by SortField )
order by SortField
or
CREATE PROCEDURE Get_Customers_By_Page
@CurrentPage int,
@PageSize int,
@TotalRecords int output
as
SELECT identity(int,1,1) as id ,* into #TempTable from table
DECLARE @FirstRec int, @LastRec int
SELECT @FirstRec = (@CurrentPage - 1) * @PageSize
SELECT @LastRec = (@CurrentPage * @PageSize + 1)
SELECT
*
FROM
#TempTable
WHERE
ID > @FirstRec
AND
ID < @LastRec
SELECT @TotalRecords = COUNT(*) FROM table
#3
create procedure cur_num @num int
as
declare @sql varchar(8000)
set @sql = 'select top '+ cast(@num as varchar(100)) + ' * from 表'
exec(@sql)
as
declare @sql varchar(8000)
set @sql = 'select top '+ cast(@num as varchar(100)) + ' * from 表'
exec(@sql)
#4
修改
create procedure cur_num @num int,@num1
as
declare @sql varchar(8000)
set @sql = 'select top '+ cast(@num as varchar(100)) + ' * from 表 where id >@num1'
exec(@sql)
create procedure cur_num @num int,@num1
as
declare @sql varchar(8000)
set @sql = 'select top '+ cast(@num as varchar(100)) + ' * from 表 where id >@num1'
exec(@sql)
#5
to: happydreamer(黑DD)
你说的意思我明白,我也这样想过,但它的效率直在值得商榷,
比如说我想取得第 500001到500100 的100条记录,那么你的语句就是:
select Top 10 * from T
where SortField NOT IN (select Top 500000 SortField
from T order by SortField )order by SortField
效率很低吧。你的另一种方法也一样,先把这么多记录倒到另一个临时表中,也一定很慢。
to: saucer(思归, MS .NET MVP) :
你说的第一页用 select top 100 * ... 我能理解。但是以后的记录你用下面的语句:
select top 100 * from yourtable where SomeField > '最后一个记录' order by
SomeField
就有一个假设:SomeField 必须是唯一索引。 如果根本就没有索引的话,该怎么办呢。
我想要的其实就是类似 select between 500001 and 500100 * from T 的这样一个语句。但又要顾及到效率。
to wgy2008(北极光) :
你说的也只是显示头一百条时的情况。
你说的意思我明白,我也这样想过,但它的效率直在值得商榷,
比如说我想取得第 500001到500100 的100条记录,那么你的语句就是:
select Top 10 * from T
where SortField NOT IN (select Top 500000 SortField
from T order by SortField )order by SortField
效率很低吧。你的另一种方法也一样,先把这么多记录倒到另一个临时表中,也一定很慢。
to: saucer(思归, MS .NET MVP) :
你说的第一页用 select top 100 * ... 我能理解。但是以后的记录你用下面的语句:
select top 100 * from yourtable where SomeField > '最后一个记录' order by
SomeField
就有一个假设:SomeField 必须是唯一索引。 如果根本就没有索引的话,该怎么办呢。
我想要的其实就是类似 select between 500001 and 500100 * from T 的这样一个语句。但又要顾及到效率。
to wgy2008(北极光) :
你说的也只是显示头一百条时的情况。
#6
SQLServer中分页只能这样了:
exec('SELECT Top '+cast(@每页大小 as varchar)+' * FROM T WHERE SortField NOT IN (SELECT TOP '+cast(@每页大小*@第几页 as varchar)+' SortField from T )')
只有oracle里有rowid速度也很快,期待sqlserver下一个版本有rowid
exec('SELECT Top '+cast(@每页大小 as varchar)+' * FROM T WHERE SortField NOT IN (SELECT TOP '+cast(@每页大小*@第几页 as varchar)+' SortField from T )')
只有oracle里有rowid速度也很快,期待sqlserver下一个版本有rowid
#7
不外乎,利用触发器,在记录变更时重新计算变更记录以后的行号。
#8
唉,看来是没有很好的解决方法了。
以上的解决方法无非有以下几种:
1. 用 select top 100 * from T where .. not in ( select top beginIndex ... ), 但是当 beginIndex 很大的时候,比如 1000000, 这样做无疑效率很低。
2. 利用索引,把每次查询后的索引值记录。但是当索引值重复很大或者根本没有索引时,这种方法就不行了。
3. 用类似 oracle里的rowid, 但是 sql-server 里没有。 :-(
我现在用的是 ado.net 里的 DbDataAdapter.Fill 方法里的功能来实现分页的,但是效率很低,所以想找一种能直接在数据库里实现的方法。
各位大侠帮忙啊
以上的解决方法无非有以下几种:
1. 用 select top 100 * from T where .. not in ( select top beginIndex ... ), 但是当 beginIndex 很大的时候,比如 1000000, 这样做无疑效率很低。
2. 利用索引,把每次查询后的索引值记录。但是当索引值重复很大或者根本没有索引时,这种方法就不行了。
3. 用类似 oracle里的rowid, 但是 sql-server 里没有。 :-(
我现在用的是 ado.net 里的 DbDataAdapter.Fill 方法里的功能来实现分页的,但是效率很低,所以想找一种能直接在数据库里实现的方法。
各位大侠帮忙啊
#9
那些都是“直接在数据库了实现”的方法啊!!!!
只有“ado.net 里的 DbDataAdapter.Fill ”才是在客户端实现的方法。
只有“ado.net 里的 DbDataAdapter.Fill ”才是在客户端实现的方法。
#10
傻了吧叽的ado.net是怎么做的呢?他把100万数据读到客户端,然后只留下需要的一页数据,剩下的再丢弃。
所以,即使你认为“很慢”的查询语句,也比你用ado.net的所谓分页功能要快不知道多少倍。
所以,即使你认为“很慢”的查询语句,也比你用ado.net的所谓分页功能要快不知道多少倍。
#11
这里,之所以慢,不在于服务器上查询中间结果需要的数据的多,而在于要将过多的结果数据在网络上传送到客户端。
#12
楼上说的对!
exec('SELECT Top '+cast(@每页大小 as varchar)+' * FROM T WHERE SortField NOT IN (SELECT TOP '+cast(@每页大小*@第几页 as varchar)+' SortField from T )')
肯定比你ado.net里做的快!
exec('SELECT Top '+cast(@每页大小 as varchar)+' * FROM T WHERE SortField NOT IN (SELECT TOP '+cast(@每页大小*@第几页 as varchar)+' SortField from T )')
肯定比你ado.net里做的快!
#13
SQLServer中分页这样比较好:
exec('SELECT Top '+cast(@每页大小 as varchar)+' * FROM T WHERE SortField NOT IN (SELECT TOP '+cast(@每页大小*@第几页 as varchar)+' SortField from T )')
速度不是很快,但是没有什么问题
exec('SELECT Top '+cast(@每页大小 as varchar)+' * FROM T WHERE SortField NOT IN (SELECT TOP '+cast(@每页大小*@第几页 as varchar)+' SortField from T )')
速度不是很快,但是没有什么问题
#14
谢谢w_rose,你说得对。我回去试一试,星期一再结帐
#15
谢谢 happydreamer(黑DD) 及各位的回答,我试了一下,你们是对的。
本来最好是数据库直接支持,即然可以有 select top N ..., 为什么不可以有类似
select between N1 and N2 ...的语句呢?
数据库直接支持的效率显示是最高的
本来最好是数据库直接支持,即然可以有 select top N ..., 为什么不可以有类似
select between N1 and N2 ...的语句呢?
数据库直接支持的效率显示是最高的
#16
学习中