如何查询 dbase 数据库中的前 20个记录(100分)

  • 主题发起人 主题发起人 yysun
  • 开始时间 开始时间
Y

yysun

Unregistered / Unconfirmed
GUEST, unregistred user!
数据库程序中需要一个排行榜功能,
我用了TQuery和order by,但是它一次返回所有上万条记录.
如何用只返回前面20条呢?
 
用filter:
1.定一个全局变量 RCount := 0;
1.filtered := true;

2. OnFilterRecord:

if RCount > 20 then Accept := false
else begin
inc(RCount);
accept := true;
end;
 
呵呵, 对分数建立一个索引,然后Table选用这个索引
并且在中Query使用游标。
等我试验一下给出一个可以运行的例子,:)
 
怎么,很简单么?根本就不需要用TQuery,
直接用TTable, 制定索引之后,简单地:
RichTable.First;
For i:=1 To 20 Do
Begin
if (RichTable.EOF) break;
// Get the values of the fields that needed and generate
// result HTML file;
RichTable.Next;
End;

搞定了!???
 
也可以这样做:
Fnd := False;
With Table1 Do
Begin
Open;
First;
While (Not Eof) and (Not Fnd) Do
Begin
if i<=指定记录 Then
Begin
{*你的程序*}
Fnd := False;
End
Else Fnd := True;

Inc(i);
Next;
End;
Close;
End;
 
文件型数据库通常在做SQL查询时, 都是完全将结果集查询到, 才开始
送出结果集, 这和C/S的数据库有很大差异, (C/S型在一些查询中
是Server先查出一部份送至客户端, 如果客户端接着还要, Server接着
再送一部份, 如果停止处理, 则无须再查,再给). 在BDE Local SQL 中
不支持Top 20 之类的句法, 所以若想查询的越快, 则需要在
Order 条件上加索引, 若要结果集小, 则可以通过 约束条件的方法减少
结果集, 使得文件结果集大于20 ,但又不太大.
例如, 一万人分数的排列,取20人,只要在分数上有索引, Order 就很快,
为了不返回1万条纪录, 可以加Where 分数 > (xxx), 减小结果集, 具体
(xxx)取多少, 就分数的分布估计情况而定吧, 最后取前20条 处理即可 ,
这样的效率至少是不加约束条件的2-3倍(有可能更高).
如果是C/S型数据库就不用加约束条件了, 数前20条出来即可.
 
我再详细解释一下问题:

已知: 原始表有2个,表1表2一对多.
表1: 用户编号, 用户名称
表2: 用户编号, 分数, 日期

求某一段时间内的分数前20位的用户排行榜
我用了 SQL (TQuery):

select 表1.用户名称, sum(表2.分数) points
from 表1, 表2
where 表1.用户编号 = 表2.用户编号 [and 日期 between "" and ""]
group by 用户名称
order by points desc

表1 记录数>5000, 表2 记录数>50000, dbf 格式, NT服务器 100M 局域网.
结果: 查询时间 > 15 分钟, 怎么办?


 
hehe, 慢就慢在您要把两个表和起来查,
只在第二个表中检索会快得多,等结果出来之后,
您选出了前二十名,然后再把用户编号对应的名字查出来就会快很多
 
不知道怎么搞的,刚才法的回答中的查询语句丢掉了

select 用户编号,sum(表2.分数) as points
from 表2
where 日期 between "" and ""
group by 用户编号
order by points desc

然后用程序只取前面20名,并查出对应的用户名称输出,
估计速度至少快20倍,:)
 
如果服务器端是数据库服务器,可以在服务器上做一个存储过程,在那里查询、排序再
返回前二十条。
但如果服务器是Access之类的文件数据库,pegasus是个不错的方案。
 
对, 如果要做存储过程也别忘了不要连接两个表查询,仍然这样在
一个表中查到结果之后,在到另一个表中拼装出最后的结果
 
可以用CLIENTDATASET,那个可以指定返回多少个数据记录。
 
其实慢的原因并不在于返回的数据记录太多,
因为为了能够排出顺序,肯定要把这些记录全部生成的,而连接两个很大的表
做查询是非常耗费时间的,只要简化成两次单独的查询,效率自然大大提高。
 
另外,每次都要临时做Sum也是慢的原因,可以在个人的数据中加入总分和当月
得分两个域,每次加分的时候添加上去,这样就能更快乐,不用Sum,您就能够直
接用TTable,选择了索引域之后就可以简单地用我前面说到的方法只取前面20 人了
 
谢谢 pegasus, 我采用了您 "简化成两次单独的查询"的解决方案.
 
效果如何? :)
谢谢版主,因为这道题目,我终于重返当月排行榜,:)
 
后退
顶部