FoxPro 9.0:如何让内循环从表2上次停止的行开始迭代
高效匹配两个有序表的解决方案
针对你提到的table1(id唯一升序)和table2(id分组升序)的匹配需求,以下是两种高效实现方式,解决内层循环重复从头扫描的问题:
方案1:单遍历双指针法(最优效率)
利用两个表id均为升序的特性,只遍历一次即可完成所有匹配和更新,完全避免嵌套循环的冗余扫描:
SELECT table1 GO TOP SELECT table2 GO TOP LOCAL lnT1Id, lnT2Id, lcResult lnT1Id = table1.id lnT2Id = table2.id SCAN -- 跳过table1中id小于当前table2 id的行(无对应数据) DO WHILE lnT1Id < lnT2Id SELECT table1 REPLACE result_field WITH "" && 替换为你的默认处理结果 SKIP IF EOF() EXIT ENDIF lnT1Id = table1.id SELECT table2 ENDDO IF EOF("table1") EXIT ENDIF -- 跳过table2中id小于当前table1 id的行 IF lnT1Id > lnT2Id LOOP ENDIF -- 处理当前id对应的所有table2行 lcResult = "" SCAN WHILE table2.id == lnT1Id -- 这里编写你的业务处理逻辑,比如拼接、计算 lcResult = lcResult + table2.data_field + ";" ENDSCAN -- 更新table1对应行 SELECT table1 REPLACE result_field WITH IIF(LEN(lcResult) > 0, LEFT(lcResult, LEN(lcResult)-1), "") SKIP IF EOF() EXIT ENDIF lnT1Id = table1.id SELECT table2 ENDSCAN -- 处理table1剩余无对应table2数据的行 SELECT table1 SCAN WHILE NOT EOF() REPLACE result_field WITH "" ENDSCAN
方案2:改进嵌套循环,基于SCAN WHILE的位置续扫
如果需要保留外层遍历table1的结构,通过记录table2的当前位置,实现每次内层循环从上次停止处开始:
SELECT table2 GO TOP LOCAL lnLastRec = RECNO() SELECT table1 SCAN LOCAL lnCurrentId = table1.id SELECT table2 GO lnLastRec && 跳转到上次处理的位置 -- 跳过所有小于当前table1 id的table2行 SCAN WHILE table2.id < lnCurrentId lnLastRec = RECNO() ENDSCAN -- 处理当前id对应的所有table2行 LOCAL lcResult = "" SCAN WHILE table2.id == lnCurrentId -- 业务处理逻辑 lcResult = lcResult + table2.data_field + ";" lnLastRec = RECNO() ENDSCAN -- 更新table1 SELECT table1 REPLACE result_field WITH IIF(LEN(lcResult) > 0, LEFT(lcResult, LEN(lcResult)-1), "") ENDSCAN
关键注意点
- 必须保证table2按id升序排列:如果原表无序,先执行
INDEX ON id TAG idx_id建立索引,或SORT TO table2_sorted ON id生成有序表,否则SCAN WHILE无法正确工作。 - 对比
SCAN FOR,SCAN WHILE在有序表上的效率提升显著,因为它是线性推进而非全局扫描。 - 数据量较大时,给table2的id字段建立索引能进一步加快定位速度。
内容的提问来源于stack exchange,提问作者DizzleBeans
相关产品推荐
相关产品推荐

