如何基于多个字段的子列表查询总表中的数据,并复制到新表? Topic is solved

遇到了问题?请先进行搜索(中文和英文),然后在此提问

Moderators: tmplinshi, arcticir

gdqb521
Posts: 13
Joined: 15 Aug 2015, 08:01

如何基于多个字段的子列表查询总表中的数据,并复制到新表?

Post by gdqb521 » 24 Aug 2022, 10:13

问题描述:子表中有3个字段,63行,要将总表(10个字段100002行)中同时包含子表三个字段的行数据找到,并复制到新的文档。
子表的三个字段分别对应总表的第2、6、7字段。
主要问题在如何提高查找的效率?我电脑上基于示例数据,用遍历循环筛选完要5秒钟左右,当数据增加时,筛选时间也呈几何倍数增长,是否有更高效的处理方式?
筛选完的行数有1027行。

示例数据:
示例.zip
包含总表和子表的两个csv文件
(1005.74 KiB) Downloaded 83 times

Code: Select all

T_start:=A_TickCount		
fulllist:=A_ScriptDir "\fulllist.csv"
sublist:=A_ScriptDir "\sublist.csv"
SplitPath, fulllist, name, dir, ext, name_no_ext, Drive
Outputfile:=dir "\out.csv"
FileDelete,%outputfile%
FileRead,fulllist0,%fulllist%
ofulllist:=StrSplit(fulllist0,"`n")
out:=""
loop, Read, %sublist%
{
	Array6:= StrSplit(A_LoopReadLine,"`,")
	for index, element in ofulllist
	{
		if (InStr(ofulllist[A_Index],Array6[1]) && InStr(ofulllist[A_Index],Array6[2]) && InStr(ofulllist[A_Index],Array6[3]) )
			out.= ofulllist[A_Index] "`n"
	}
}
FileAppend, %out%,%Outputfile%,utf-8
MsgBox, % A_TickCount-T_start "ms"    ;7219ms
ExitApp

kazhafeizhale
Posts: 77
Joined: 25 Dec 2018, 10:58

Re: 如何基于多个字段的子列表查询总表中的数据,并复制到新表?

Post by kazhafeizhale » 24 Aug 2022, 23:26

SetBatchLines, -1
脚本加这个会加速

gdqb521
Posts: 13
Joined: 15 Aug 2015, 08:01

Re: 如何基于多个字段的子列表查询总表中的数据,并复制到新表?

Post by gdqb521 » 25 Aug 2022, 02:13

kazhafeizhale wrote:
24 Aug 2022, 23:26
SetBatchLines, -1
脚本加这个会加速
测试确实提高了速度,时间缩短了一半。
还有没有更高效的办法,主要是正式数据差不多是现在的10~100倍,然后处理一次都是几个小时,实际需求需要很多次处理。所以时间要求较高。

kazhafeizhale
Posts: 77
Joined: 25 Dec 2018, 10:58

Re: 如何基于多个字段的子列表查询总表中的数据,并复制到新表?

Post by kazhafeizhale » 25 Aug 2022, 07:19

gdqb521 wrote:
25 Aug 2022, 02:13
kazhafeizhale wrote:
24 Aug 2022, 23:26
SetBatchLines, -1
脚本加这个会加速
测试确实提高了速度,时间缩短了一半。
还有没有更高效的办法,主要是正式数据差不多是现在的10~100倍,然后处理一次都是几个小时,实际需求需要很多次处理。所以时间要求较高。

Code: Select all

SetBatchLines, -1
T_start:=A_TickCount		
fulllist:=A_ScriptDir "\fulllist.csv"
sublist:=A_ScriptDir "\sublist.csv"
SplitPath, fulllist, name, dir, ext, name_no_ext, Drive
Outputfile:=dir "\out.csv"
FileDelete,%outputfile%
FileRead,fulllist0,%fulllist%
ofulllist:=StrSplit(fulllist0,"`n")
hash := {}
for index, element in ofulllist
{
	Array6:= StrSplit(element,"`,")
    key := Array6[2] Array6[6] Array6[7]
    if(hash.HasKey(key))
        hash[key].Push(element)
    Else
        hash[key] := [element]
}
out := ""
loop, Read, %sublist%
{
	Array6:= StrSplit(A_LoopReadLine,"`,")
    key := Array6[1] Array6[2] Array6[3]
    if(hash.HasKey(Key))
    {
        for k,v in hash[key]
        {
            out .= v "`n"
        }
    }
}
FileAppend, %out%,%Outputfile%,utf-8

gdqb521
Posts: 13
Joined: 15 Aug 2015, 08:01

Re: 如何基于多个字段的子列表查询总表中的数据,并复制到新表?

Post by gdqb521 » 25 Aug 2022, 21:05

非常感谢@kazhafeizhale,你的代码效率提高很多。
我将我的完整需求在下面代码中进行的展示,也待优化。
需求是从fulllist中查找关键字,要求在同一个“订单号”项下查找“商品ID”中同时包含kw01和kw02的用户ID等信息,并生成sublist
基于以下代码也能实现,但是和@kazhafeizhale优化后后面的代码比,效率太低了。能否优化。
@kazhafeizhale的代码,我还在学习中。请赐教!
以下代码实现基于商品ID关键词实现生成sublist,然后在生成out。
商品ID的ini:

Code: Select all

[kw01]
31710
36711
38711
39711
[kw02]
30710
35710
37710
待优化代码:

Code: Select all

SetBatchLines, -1   ;默认的10ms改为全速运行,cpu使用率会高一些,但是运行时间大约可以缩短一半
T_start:=A_TickCount
; 从fulllist.CSV的同一个“订单号”获取“商品ID”中查找同时包含kw01和kw02的用户ID等信息生成sublist
kw01:="(,31710,|,36711,|,38711,|,39711,)"
kw02:="(,30710,|,35710,|,37710,)"
Array_kw01:=[] ,	Array_kw02:=[]

fulllist:=A_ScriptDir "\fulllist.csv"
sublist:=A_ScriptDir "\sublist.csv"
SplitPath, fulllist, name, dir, ext, name_no_ext, Drive
Outputfile:=dir "\out.csv"
FileDelete,%outputfile%
FileDelete,%sublist%
FileRead,fulllist0,%fulllist%
ofulllist:=StrSplit(fulllist0,"`n")
; 生成sublist,待优化
	for key,Value in ofulllist
		{
			if (RegExMatch(Value, kw01 ) !=0)
			{
				Array2:=[]
				loop, Parse, Value, CSV
					Array2.Push(A_LoopField)
				复合ID2:= array2[2] "_" array2[6] "_" array2[7]
				Array_kw01.Push(复合ID2)
			}
			if (RegExMatch(Value, kw02 ) !=0)
			{
				Array2:=[]
				loop, Parse, Value, CSV
					Array2.Push(A_LoopField)
				复合ID2:= array2[2] "_" array2[6] "_" array2[7]
				Array_kw02.Push(复合ID2)
			}
		}
		; 从筛选得到的两个数组中取交集ID
		订单列表:=""
		for k,v in Array_kw02
		{
			for m,n in Array_kw01
			{
				if (v=n)
					订单列表.= n "`n"
			}
		}
		Sort,订单列表,U
	订单列表:=StrReplace(订单列表,"_","`,")
		; 将排序去重后的列表进行写入文件
		FileAppend,%订单列表%,%sublist%,utf-8
; ======生成sublist结束===代码待优化===========



hash := {}
for index, element in ofulllist
{
	Array6:= StrSplit(element,"`,")
    key := Array6[2] Array6[6] Array6[7]
    if(hash.HasKey(key))
        hash[key].Push(element)
    Else
        hash[key] := [element]
}
out := ""
loop, Read, %sublist%
{
	Array6:= StrSplit(A_LoopReadLine,"`,")
    key := Array6[1] Array6[2] Array6[3]
    if(hash.HasKey(Key))
    {
        for k,v in hash[key]
        {
            out .= v "`n"
        }
    }
}

FileAppend, %out%,%Outputfile%,utf-8
MsgBox, % A_TickCount-T_start "ms"    ;耗时359ms
ExitApp


kazhafeizhale
Posts: 77
Joined: 25 Dec 2018, 10:58

Re: 如何基于多个字段的子列表查询总表中的数据,并复制到新表?

Post by kazhafeizhale » 26 Aug 2022, 04:24

思路就是先构造 关联数组,然后再查找

sikongshan
Posts: 19
Joined: 06 Jul 2019, 21:57

Re: 如何基于多个字段的子列表查询总表中的数据,并复制到新表?  Topic is solved

Post by sikongshan » 28 Aug 2022, 03:43

学习了,@kazhafeizhale 构建数组的思路很不错。
后面的需求,我试了一下,当把数据表复制到10倍的时候,有点时间差。
可能并没有完全理解。

Code: Select all

SetBatchLines, -1

T_start:=A_TickCount
oa:=object()
ob:=object()
Loop, read, fulllist.csv ;根据“fulllist”里面的267构建两个表  表A==匹配客户id1  表B==匹配客户id2
{
	ArrSplit:=StrSplit(A_LoopReadLine,"`,")
	var9:= ArrSplit[9]
	var267:=ArrSplit[2] "`,"ArrSplit[6] "`,"ArrSplit[7]

	if var9 in 31710,36711,38711,39711
		oa[var267]:=1
	else if var9 in 30710,35710,37710
		ob[var267]:=1
}

结果:=""
Loop, read, fulllist.csv
{
	Array6:= StrSplit(A_LoopReadLine,"`,")
    key := Array6[2] "`," Array6[6] "`," Array6[7]  ;注意连接符是逗号
    if(ob.haskey(key) and oa.HasKey(key))  ;再次读取“fulllist”,再看267是否同时存在于表a和表b
    {
        结果.= A_LoopReadLine "`n"
    }
}
用时:=A_TickCount-T_start
FileAppend, %结果%,【方案0】【%用时%】----------%A_Now%.txt,utf-8  ;多个方案 ,loop多次运行,可以对比用时

gdqb521
Posts: 13
Joined: 15 Aug 2015, 08:01

Re: 如何基于多个字段的子列表查询总表中的数据,并复制到新表?

Post by gdqb521 » 29 Aug 2022, 03:45

@sikongshan 感谢,这个确实提高的很多,而且用的很巧妙。
虽然我还不能完全理解为什么这样做效率高,但是他确实是目前最高效的实现方式。
再次感谢@kazhafeizhale@sikongshan 的指导。

Post Reply

Return to “请求帮助”