AdoDataSet1和AdoDataSet2两个数据集结构一样,主键为字段Ryid,每个库均有2000个以上记录,现要求一个最高效率的算法:比较两个数据集中的记录,如果AdoDataSet1中的记录AdoDataSet2中没有,则把这条记录添加至AdoDataSet2中。 因为数据集来源有些字段不是来自表,不能用SQL语句来比较记录来合并不同值。
我用传统的算法:
var
ls_ryid:string;
i:Integer;
begin
AdoDataSet1.First;
AdoDataSet2.First;
while Not AdoDataSet1.Eof do
begin
ls_ryid:=AdoDataSet1.FieldbyName('Ryid').AsString;
if Not AdoDataSet2.Loacte(Ryid,ls_ryid,[]) then
AdoDataSet2.Append;
for i:=0 to AdoDataSet2.Fields.Count-1 do
AdoDataSet2.Fields[i].value:=AdoDataSet1.Field[i].value;
AdoDataSet1.Next;
end;
end;
这样很慢,原因有3:
1,对AdoDataSet1进行了所有记录的循环。
2,对AdoDataSet2进行了Loacte方法
3,对字段赋值进行了逐一字段的赋值: AdoDataSet2.Fields[i].value:=AdoDataSet1.Field[i].value;以上是问题所在,
谁能帮忙想想,有提高效率的更好方法吗?
我用传统的算法:
var
ls_ryid:string;
i:Integer;
begin
AdoDataSet1.First;
AdoDataSet2.First;
while Not AdoDataSet1.Eof do
begin
ls_ryid:=AdoDataSet1.FieldbyName('Ryid').AsString;
if Not AdoDataSet2.Loacte(Ryid,ls_ryid,[]) then
AdoDataSet2.Append;
for i:=0 to AdoDataSet2.Fields.Count-1 do
AdoDataSet2.Fields[i].value:=AdoDataSet1.Field[i].value;
AdoDataSet1.Next;
end;
end;
这样很慢,原因有3:
1,对AdoDataSet1进行了所有记录的循环。
2,对AdoDataSet2进行了Loacte方法
3,对字段赋值进行了逐一字段的赋值: AdoDataSet2.Fields[i].value:=AdoDataSet1.Field[i].value;以上是问题所在,
谁能帮忙想想,有提高效率的更好方法吗?
有些字段不是来自表,应该也还是有间接方法采用SQL进行数据合并?
1。不要在遍历的过程中插入,在不改变任何内容的情况下遍历原数据集应该是很快的,这个时候使用一个TList记录下所有的书签;
2。遍历完后不要关闭数据集,读内存中的所有书签,然后再对目标数据集进行插入;
3。在循环开始处就用.Last读入所有目标数据集的记录,而记录没有改变的情况下,Locate的速度应该会比较快。
以上几点纯属猜想-___-b
AdoDataSet2.Fields[i].value:=AdoDataSet1.Field[i].value;
AdoDataSet1.Next;
因为每次数据集的循环,都会对每个字段循环赋值。谁能想到一个方法对AdoDataSet2和AdoDataSet1之间的字段赋值的其他办法?有不有直接把AdoDataSet1当前记录整个赋给AdoDataSet2,而不是一个一个字段赋值?如果能解决这个问题,估计速度将大大提速。
1。不要用数据集的First、NEXT,研究一下ADODATASET.RECORDSET,用它访问数据集数据效率要快。
具体怎么用到网上找一下就知道了。
2.可以试一下两个ADODATASET都用主键做相同索引(ADODATASET里有个INDEXFIELDNAMES属性)。
用相同顺序互相对比。效率应该是O(n)。
到了临时表里以后insert into 2 where key_field not in (select key_field from xxx表) 不就得了?
begin
//
end;procedure PostBufferToAdoDataSet2;
begin
//
end;procedure Compare2Tables;
begin
AdoDataSet1.First;
AdoDataSet2.First;
repeat
if AdoDataSet1.FieldbyName(Ryid).AsInteger = AdoDataSet2.FieldbyName(Ryid).AsInteger then begin
AdoDataSet1.Next;
AdoDataSet2.Next;
end else if AdoDataSet1.FieldbyName(Ryid).AsInteger > AdoDataSet2.FieldbyName(Ryid).AsInteger then begin
AdoDataSet2.Next
end else if AdoDataSet1.FieldbyName(Ryid).AsInteger < AdoDataSet2.FieldbyName(Ryid).AsInteger then begin
AddToBuffer;
AdoDataSet1.Next;
end;
until(AdoDataSet1.EOF);
PostBufferToAdoDataSet2;
end;两个数据集各扫描一遍.
http://topic.csdn.net/t/20061018/21/5092570.html
强人的做法。求并的方法就简单了,得到不存在的数据后,直接写个SQL:
insert into table2 (field1, field2....) select field1, field2... from table1 where id in (id1, id2, id3...)这样最快了。
还adotable1.append....,比较晕人的法子。
select * from table1 t1
where not exists( select 1 from table2 where id = t1.id )