如何编写Google Sheets QUERY函数避免插入列后查询失效?
你遇到的问题根源在于对Google Sheets QUERY函数列引用方式的误解:QUERY语句里的C、D这类字母,是相对于你第一个参数指定的数据范围的相对列(范围的第1列对应A,第2列对应B,以此类推),而不是工作表的绝对列。
举个例子,你原公式里的Transactions!C$6:F是四列(C、D、E、F),此时QUERY里的C其实指的是这个范围的第3列(也就是工作表的E列),而不是你以为的工作表C列——这就埋下了隐患。当你在C列左侧插入新列后,原C列变成了D列,公式的自动更新把数据范围改成了Transactions!D$6:G,但QUERY语句里的C还是指向这个新范围的第3列,自然就跑到了你不想引用的列上。
给你两个简单有效的解决方案:
方案1:使用绝对列引用(推荐)
直接在QUERY语句里明确引用工作表的绝对列,同时把第一个参数设为一个足够覆盖所有数据的范围(比如A:Z),这样不管怎么插入/删除列,查询的都是你指定的那些列。
修改后的公式如下:
=QUERY(Transactions!A:Z, "select C, D*-1, E, F where C > date '1990-01-01'", 0)
这里的C、D会被QUERY识别为工作表的绝对列,再也不会因为范围偏移而跑偏。A:Z可以根据你的实际数据范围调整,比如如果数据不会超过J列,改成A:J也没问题。
方案2:用INDIRECT锁定数据范围
如果你不想改变原来的列引用逻辑,可以用INDIRECT函数把数据范围固定下来,这样插入列时范围不会自动更新。
修改后的公式:
=QUERY(INDIRECT("Transactions!C$6:F"), "select C,D*-1,E,F where C > date '1990-01-01'", 0)
INDIRECT会把字符串形式的引用解析成实际的单元格范围,而且不会随列的插入/删除自动调整,这样QUERY里的相对列引用就始终对应你原本的C-F列。唯一需要注意的是,INDIRECT是易失性函数,超大表格里可能会有点性能影响,但日常使用完全没问题。
最后给你个小建议:以后写QUERY时,也可以用Col1、Col2这种写法指代范围的相对列(比如select Col1, Col2*-1),这样更清晰,不容易搞混相对和绝对列的概念。
内容的提问来源于stack exchange,提问作者Nick

