【问题标题】:finding the max value in a database with delphi使用delphi在数据库中查找最大值
【发布时间】:2018-11-13 20:51:27
【问题描述】:

我正在使用 Delphi 2010。我有一个名为 tblUserInfo 的 Microsoft Access 数据库,其中有一个名为 NUMOFREPORTS 的字段,其中包含 11 个数字。我需要搜索数据项并找到最大数量并将其存储在变量中。 我的计划是将数据库中的值分配给一个整数数组,然后对数组进行排序以找到最大值。

这是我目前所拥有的:

i:=1;
while NOT tblUserInfo.eof do
begin
  arrNumOfReps[i]:= tblUserInfo['NUMOFREPORTS'];
  tblUserInfo.Next;
  INC(i);
end;

NumOfReps:= arrNumOfReps[1];
for I := 1 to length(arrNumOfReps) do
begin
  if arrNumOfReps[i] > NumOfReps then
  begin
    NumOfReps:= arrNumOfReps[i];
  end;
  showmessage(inttostr(NumOfReps));
end;

当我运行该程序时,它不起作用并在NumOfReps:= arrNumOfReps[1]; 处中断,并且我收到一条错误消息,显示“访问冲突”。

有人对我的代码或替代解决方案有任何更正吗? 谢谢

【问题讨论】:

  • 您的做法完全错误。您应该对您的表使用 Select Max(
  • 正如@MartynA 所指出的,让数据库来完成这项工作。并阅读:stackoverflow.com/questions/17308246/access-violation-in-delphi,看看 Mason Wheeler 的回答。
  • 为什么要以最慢的方式执行此操作?只需执行select max(NUMOFREPORTS) from tblUserInfo 即可。接受@MartynA 的建议
  • 我感觉select count(NUMOFREPORTS) from tblUserInfo 更适合您。如果您有删除历史记录的空白怎么办? MAXCOUNT 无关。

标签: arrays database delphi delphi-2010


【解决方案1】:

正如 MartynA 在 cmets 中指出的那样,您应该让数据库为您找到最大值,而不是先检索所有值,然后自己搜索最大值。为什么?

  1. 在您的情况下,您声称您在此字段中只有 11 个值,因此从数据库中检索该数据并不困难。但是,如果你在那里有一百万个值怎么办。从数据库中检索 100 万个值可能会给数据库带来很大负担,并且如果您将这些值存储在数组中以供进一步处理(查找最大值),还会消耗客户端计算机上的大量内存。
  2. Database 肯定能够比您更快地找到最大值,因为它可以轻松地将这项任务分配给多个内核。更不用说如果该特定字段被索引,则数据库很可能已经将最大值存储为索引值之一,在这种情况下,数据库可以立即返回最大值。即使最大值不直接存储为索引值数据库之一,也只需检查部分记录,而不是检查每一条记录。

如果由于某种特殊原因你真的不能使用数据库内置的Select Max函数(也许值不是存储为数值而是存储为特殊字符串,最大值由中间的某个部分确定)字符串)并且必须自己真正找到最大值不要费心将所有值存储到数组中。而是在从数据库中检索记录时直接进行所需的比较以找到最大值。也许是这样的,我刚刚修改了您的循环以从数据库中检索记录:

while NOT tblUserInfo.eof do
begin
  if tblUserInfo['NUMOFREPORTS'] > NumOfReps then
  begin
    NumOfReps:= tblUserInfo['NUMOFREPORTS'];
  end;
  tblUserInfo.Next;
end;

【讨论】:

  • 由于您对问题的良好解释,我对此表示赞同,但我认为您应该通过不在循环中使用 ['FieldName'] 构造来改进您的答案,尤其是每次迭代两次。最好在开始循环之前在本地 TField 变量中捕获字段的缩进并针对它进行读取。
  • @MartynA 我回答的目的是让它易于理解。但我完全同意您对代码示例的优化建议。
【解决方案2】:

你是如何声明你的数组的?根据您使用它的方式,它可能应该这样声明:

var
  ArrNumOfReps: array[1..12] of Integer;

但这是有限的,因为该程序最多只支持 11 个值。而是使用动态数组

var
  ArrNumOfReps: array of Integer;

i:=0;
while NOT tblUserInfo.eof do
begin
  SetLength(ArrNumOfReps, Length(ArrNumOfReps) + 1);
  arrNumOfReps[i]:= tblUserInfo.FieldByName('NUMOFREPORTS').AsInteger;
  tblUserInfo.Next;
  INC(i);
end;

这将允许程序使用可变数量的代表。

【讨论】:

  • 认真的吗?每次围绕将执行不确定的,可能是巨大的,多次循环的循环调用 SetLength?无论如何,鼓励 OP 坚持使用这种方法的愚蠢行为并不是一个好主意
  • @MartynA 同意。我是专门回答 OP 的问题,而不是试图给他一个如何编写更好代码的教程。
  • @nolaspeaker 问题在于 OP 不会学习并且会继续返回这里并提出糟糕的问题。
  • @Jerry Dodge 我会给他更多的信任。
猜你喜欢
  • 2019-04-22
  • 1970-01-01
  • 2014-05-15
  • 2018-01-08
  • 2011-08-18
  • 2015-04-19
  • 2017-04-19
  • 2011-03-06
  • 1970-01-01
相关资源
最近更新 更多