少一次连接提一次速度
周二中午去吃饭的时候,我突然意识到之前我用VBA+ADO+SQL做跨表查询的时候,把条件参数也当作是一个表。起码在PQ和PP方案里是这样的。在python方案里,我没有把条件参数作为第三个表,我只是直接把数据从Excel的单元格里读取,然后赋值给一个变量,在以后的各种比较之中用。 python的变量相对于VBA来说实在是太自由了,除非是列表元组字典之类要先定义,然后再用,其它都是拿起来就干,不管他什么格式,日期也好,字符串也好,数值也好,都无所谓。之前我之所以没有在VBA+ADO+SQL里把几个日期参数作为变量是因为我不知道如何在字符串形式的SQL里加入变量,正如一开始的时候,我不知道该如何让让下一个SQL用上一个SQL的结果,但现在我已经用得很顺畅了,整个流程下来,我要引用好多遍,有些是引用上一行的,有些是引用好久好久之前的,说白了就是双引号加&加变量加&再加双引号,等于是把变量以外的东西用双引号括起来。所以既然上一个SQL查询可以这么用,为什么我的那些固定参数就不可以这么用呢。显然在VBA里,要把某个工作簿某个工作表的某个单元格数据变成变量实在太简单了。唯一的问题可能是Excel读取那个单元格的数据,那个数据的格式可能跟我料想的不太一样。比如有时Excel觉得那是一个字符串,但有时Excel又觉得那是一个日期,明明某个数据就是一个整数,但是Excel识别出来经过SQL之后直接生成的那个,Excel觉得那个东西是日期。我不知道Excel到底是怎么想的,但是Excel的单元格毕竟不是一个数据库,不像PQ那样,进到PQ里面,如果你得在某些列进行运算处理的话,你就得定义它为你的目标格式而不能让系统默认成为它们觉得的样子。
吃过午饭后我就赶紧去验证我的想法,结果如我所料,那些变量的确能直接通过拼接的方式加到 SQL的查询字符串里,但是拼接的方式又有点出乎我的意料。比如单元格数据读取能识别到那是一个日期,那个变量在本地窗口显示,那就是一个日期,因为那个数据左右是有#的,但问题是当我要把那个数据跟SQL查询里从表获取的其它数据比较的时候怎么比怎么不对劲。之前当我把那个条件参数作为一个表跟其它表的某些字段比较的时候,两个字段我都加了CDate这个公式,也就是我强行把他们可能觉得是字符串的东西转成日期,然后对比。把日期变量放到SQL字符串里连接符都对了,但是就是得不到我想要的结果。在调试过程中我看了一下系统识别到的那个字符串,结果发现虽然那个明明是日期,但是连接上去以后居然就变成了一个不知道该如何称呼的东西。不能说是数值,不是日期也不是字符串,所以我在双引号的之前之后又加了#,让这个四不像的日期在系统的解释之后成为真正的日期,然后再跟其它表的日期字段比较。除了日期变量以外,我的参数还有字符串。字符串变量情况跟日期很相似,所以我做的是在双引号的前后加上单引号。这样的话,经过系统的解释这就是一个一本正经的字符串了。为什么我不在读取单元格数据的时候直接在那个变量前后加#或者单引号呢?因为我发现这般操作跟在写SQL的时候再加#或者单引号相比前者耗时更长。这其中的原理我不懂。
最终,当我的跨表查询从三表变成两表,第三个表的那些内容改成直接赋值以后,整个程序的运行时间马上提升了0.3秒(效率提高30%)。这是一个了了不起的成绩。对老手来说,理论上一开始就应该这么干,我一开始也曾经试过,但当时我实在不知道该如何把字符串拼接上去。
VBA是个很成熟的东西,SQL也是一个很成熟的东西,但是当要在Excel的VBA里玩SQL的时候,可直接借鉴的经验真的少之又少,但这种摸着石头过河的感觉挺好,虽然已经让我到达了某种废寝忘食的程度了。