这是一个SQL汇总的难题,不知哪位高手能解(200分)

  • 主题发起人 主题发起人 retun
  • 开始时间 开始时间
R

retun

Unregistered / Unconfirmed
GUEST, unregistred user!
aSQL=('Create Table nvConstl(FNo integer default 0,FSeq integer default 0,FSrvType varchar(4) default '',FSrvItm varchar(8) default '',FQty integer default 0,FPrice numeric(14,2) default 0,FSum numeric(14,2) default 0,FlSerial varchar(1) default '',FBranchFlag varchar(2) default '',FWorker varchar(8) default'',Primary Key(FNo,FSeq))''');
//上面是aSQL的值,下面是进行汇总,在数据量极少的情况下,是无任何问题
//只是速度慢而已,这个小是指一两百条到上千吧,而达到6万条的时候,
//我跟踪下去,等一个小时也不见有结果。不知哪位能优化下面的代码呢?
代码:
var
  j: integer;
begin
  with qryTmp do begin
    SQL.Clear;
    for j:=Low(aSQL) to High(aSQL) do
      SQL.Add(aSQL[j]);
    ExecSQL;
  end;
end;
 
按什么进行汇总?
 
老兄,是不是贴错了。
只是看你建了一个表,没看见什么汇总
 
老兄,请说清楚问题
 
按哪几个字段汇总要说清楚呀!
最好连SQL语句给我们
 
上面那段是少了前面的代码,因为我只在这个建表后执行的时候卡着很久。新建表后
将会把原表中的数据按日期要求过虑出来加进新表中。nvConsLog是父表,nvConsStl
为子表
代码:
procedure TfrmDataTran.UpLoad;
var
  sDateRng, sFile: string;
  procedure ExtractToTmp(const sTbName, sFor: string);
  var
    sTem: string;
  begin
    sTem := GetTableStr(sTbName,False);
    TmpTableCreate(sTbName, sTem);
    sTem := StrFlds(sTem);
    if sFor<>'' then
      TmpExecQuery(['Insert Into '+sTbName+'('+sTem+')',
                    'Select '+sTem+' From '':Ais:'+sTbName+'''',
                    'Where '+sFor])
    else
      TmpExecQuery(['Insert Into '+sTbName+'('+sTem+')',
                    'Select '+sTem+' From '':Ais:'+sTbName+'''']);

//    sFile := sFile + ' ' + sTbName+'.db';
  end;
begin
  sDateRng := ' between '''+edDateSt.Text+''' and '''+edDateEnd.Text+'''';
//edDateSt.Text 和 edDateEnd.Text 为限制的日期
  ExtractToTmp('nvConsLog', 'FOutDate'+sDateRng);
  ExtractToTmp('nvConsStl', 'FNo In (Select FNo From nvConsLog '+
                                    'Where FOutDate'+sDateRng+')');
end;

procedure TfrmDataTran.TmpExecQuery(aSQL: array of string);
var
  j: integer;
begin
  with qryTmp do begin
    SQL.Clear;
    for j:=Low(aSQL) to High(aSQL) do
      SQL.Add(aSQL[j]);
    ExecSQL;
  end;
end;
 
TmpExecQuery(aSQL: array of string);直接用变参,不要用数组,或许好一点:

TmpExecQuery(var aSQL: string);
调用时将字符串直接连接“+”

procedure TfrmDataTran.TmpExecQuery(var aSQL:string);
begin
with qryTmp do begin
SQL.Clear;
SQL.Add(aSQL);
ExecSQL;
end;
end;
 
稍稍看了一下,
最好把日期FOutDate'加个索引:)
Primary Key(FNo,FSeq))''');
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~这个改为 Primary Key(FNo))''');
FSEP我没看到哪地方用到了
 
首先先谢谢两位!
TO:天真:这两个关键字不能少的,FNo是父表中的关键字来的,FSEQ是这边的关键字

FNO FSEQ
1 1
1 2
1 3
2 1
2 2
3 3
。。。。。
在主表中FNO是唯一关键字
大家应该见到在建表中没有日期这两个字段,他们都在主表中,现在的算法会由 1去找
主表中的1的东西,然后得出日期,再进行选择。请大家继续给意见!

现在的难点可能在如果进行更优化的查找和过滤
大家就把主表当成有 FNO FNAME FDATEI 三个字段,关键字段为FNO

 
看了半天,不明白你的要求是什么?
你只有一个表啊。
你把要求说清楚,是要怎么样汇总?只看代码,不知你写的对不对,也不知你的最终需求是什么,没法下手。
 
从你上面的SQL语句看
你可以建成个索引,该索引包括,FNo,FOutDate
这两个字段,
还有,你觉得速度慢,你先测一下,究竟时间是卡在哪一块上面的!:)
 
还有FOutDate是不是日期型的????
如果是
sDateRng := ' between '''+edDateSt.Text+''' and '''+edDateEnd.Text+'''';
改成
sDateRng := ' between '+edDateSt.Text+' and '+edDateEnd.Text;

原因,从日期型转换为字符型比较是很费时间的
 
TO:天真:
不是日期型的,这是一张消费明细单来的,分为主表和子表,为什么要做这步的分析和
提取呢?我来说说目的吧:
为了能把数据按要求提取出来,然后汇总成压缩包上传到FTP中去,但现在就是在按日期
过滤并提取到新建表中去,然后打包这个表上传,(这里大家要注意一个是SQL的数据库,
而打包的是DB的数据库,所以我建了一个表来将数据取出来,然后放进新表中。)当数据
量只有几天的话,这就只会显得慢而已,而数据量达到一个月的话,等一个小时都没反应
程序就象死了一样。现在就在想是否能快速的过滤方式,我也说过主表中才有日期,而汇
总的不是主表,是子表!
另我跟踪的时候,发现是卡在建表的地方
for j:=Low(aSQL) to High(aSQL) do
SQL.Add(aSQL[j]);
ExecSQL; //到了这就无法运行了
而之前有几个表汇总是过了的,只是到了这个表就如死机一样
大家不需要理主表,我也说过主表把他当成有一个日期一个FNO就行了。

再次感谢以上的各位!!!!!!
 
建表一步一步的试
 
aSQL=('Create Table nvConstl(FNo integer default 0,FSeq integer default 0,FSrvType varchar(4) default '',FSrvItm varchar(8) default '',FQty integer default 0,FPrice numeric(14,2) default 0,FSum numeric(14,2) default 0,FlSerial varchar(1) default '',FBranchFlag varchar(2) default '',FWorker varchar(8) default'',Primary Key(FNo,FSeq))''');
????应该这样才对呀
aSQL='Create Table nvConstl(FNo integer default 0,FSeq integer default 0,FSrvType varchar(4) default '',FSrvItm varchar(8) default '',FQty integer default 0,FPrice numeric(14,2) default 0,FSum numeric(14,2) default 0,FlSerial varchar(1) default '',FBranchFlag varchar(2) default '',FWorker varchar(8) default'',Primary Key(FNo,FSeq))';


 
这样建表很快呀!???
我真怀疑是我跟你说的那个原因,
你好好看看!!!!
再建议:如果真是字符型 的就好改成DATETIME,
速度会快很多
 
for j:=Low(aSQL) to High(aSQL) do
SQL.Add(aSQL[j]);
ExecSQL; //到了这就无法运行了
改为
SQL.Add(aSQL);
ExecSQL; //到了这就无法运行了
 
建表是用了一个方法来建的,我用aSQL这个值写出来只是告诉大家我跟踪到这句语句中
ASQL的值就是这上面这一个。
而字符类型是不能改的了,为了方便控制,全用了字符型,一改就影响很大。而这段程序
可以说是没有错的,只是我觉得速度非常的慢,可以说是无法忍受,数据量小还没事,一
大了就慢,对SQL来说,六万条数据是不多,不过在这里,我想这个算法中已经不止这点因
为要去查主表中这个是否为所限定的日期范围,我想问题关键在算法上。
而现在的代码也没问题的,因为对于汇总10天八天的数据是五六分钟就可以汇总出来。
 
你是跨库的呀如果两台数据库是远程的话就当然慢了如果不是远程的话就不会有问题的
如果是远程的话最好是导入导出的方法
 
是本地服务器,其实如果按1000(父表)*60000(子表)=6000W条记录量,是蛮大的了吧,
所以一直在想是否有办法变得更快些。
 
后退
顶部