Power Query 实练:5 道「只有刷新时才暴露」的题

五道题,讲的都是「在编辑器里看着没问题、一刷新就失败」的查询——查询一旦投入真实使用,这就是唯一要紧的失败模式。每组先讲成因,再给你一个情形去判断。

Power Query 点几下就能学会,却很难让它一直能用,因为几乎所有会出错的地方都不在你搭建它的时候出错。编辑器里的预览是对的;失败发生在几天之后的某次刷新上,而且常常是在别人的机器上。

三个成因解释了其中大部分。用浏览选文件的方式建的查询会记下那个绝对路径,所以文件一移动、或者工作簿在别处被打开,查询就断。Power Query 在导入时自动插入的「更改的类型」步骤会硬编码每一个列名,所以上游改个名就能让刷新失败——哪怕你根本没用过那一列。而合并会不加警告地改变行数:右表有重复键时左外部联接会把行乘出来,内部联接则会静默丢掉没匹配上的行。

下面的内容适用于 Microsoft 365 与 Excel 2021 里的 Power Query,同样的行为在 Power BI 中也存在。每题先自己判断,再看答案。

三个成因,五道题

查询一换机器就断

1 道题

用「获取数据」点出来的查询,会把你选中那个文件的绝对路径——比如 C:\Users\you\Documents\sales.xlsx——记在查询内部。一切正常,直到文件被移动、文件夹被改名,或者同事在自己机器上打开这个工作簿:此时刷新会以数据源错误失败,不会回退到任何别的东西。可持续的做法是把路径放进一个单元格、加载成参数,让查询引用这个参数——这样换个位置只是改一个单元格,而不用钻进编辑器。

通常怎么表现「Power Query 找不到文件」·「DataSource.Error:文件未找到」

第 1 题

你基于「文档」文件夹里的一个文件建了查询,然后把工作簿发邮件给同事。他们点「全部刷新」。会发生什么?

  1. A正常——数据已经加载进工作簿了
  2. B刷新失败,因为查询里存的是你的绝对路径,而那个路径在他们机器上不存在
  3. CExcel 会自动提示他们浏览选择文件
  4. D能用,但只返回缓存过的那些行
看答案与解析

正确答案B. 刷新失败,因为查询里存的是你的绝对路径,而那个路径在他们机器上不存在

🐱 加载好的结果确实会随工作簿一起走,所以在有人刷新之前表看起来完全正常——这正是它难以诊断的原因。查询步骤本身记着你的路径,在另一台机器上这个路径解析不到任何东西,于是刷新抛出数据源错误。修法是把路径参数化;用共享网络位置或 SharePoint 作源也行,因为那样路径对每个人都一样,而不是绑在某一个用户配置上。

源数据加了一列,昨天还好好的查询今天就炸了

1 道题

Power Query 把你做过的事记成一串字面的步骤,而其中好几个步骤会把列名硬编码进去——「更改的类型」会按名字列出每一列,「删除的列」和「重命名的列」同样如此。上游改了某个列名,或者源本身列的顺序变了,那个提到它的步骤就会以「找不到列」失败。能避掉大部分这类问题的习惯是:把 Power Query 在导入时自动插入的那个「更改的类型」步骤删掉,改到最后、等表的形状稳定之后再统一设类型。

通常怎么表现刷新后「找不到列」·「Expression.Error:未找到表的列 'X'」

第 2 题

你的查询导入一个 CSV。供应商把「Amount」改名成了「Amount (USD)」。刷新在「更改的类型」这一步失败。这一步为什么会在乎列名?

  1. A「更改的类型」会校验每一列是否仍是原来的数据类型
  2. B「更改的类型」里存的是一份显式的「列名 → 类型」清单,所以改了名的列就等于不见了
  3. C只要表头变了,CSV 导入就一定会失败
  4. D架构一变,这一步就需要手动刷新一次
看答案与解析

正确答案B. 「更改的类型」里存的是一份显式的「列名 → 类型」清单,所以改了名的列就等于不见了

🐱 「更改的类型」并不是一条「去检测类型」的通用指令——它是一份记录下来的清单,大致是「Amount → 数字,Date → 日期,Region → 文本」。当 Amount 不再存在,那一条就没法应用,步骤于是报错。由于 Power Query 在导入时会自动插入这一步,它成了刷新失败的头号来源。把自动插入的那一步删掉、改到最后统一设类型,能让查询对「那些并不影响你真正用到的列」的上游改名保持宽容。

合并查询:会静默改变行数的那个联接类型

2 道题

合并会问你要哪种联接类型,默认的「左外部」保留第一个表的每一行、并把第二个表的匹配项附上去。接下来有两件事经常让人意外。如果第二个表每个键有不止一行,左联接会把行乘出来而不是挑一条——一张一百行的表可能变回来一百四十行。而「内部」联接——大家常因为它听着更干净而选它——会静默丢掉第一个表里所有没匹配上的行。两者都不报错,所以唯一可靠的检查是比对合并前后的行数

通常怎么表现「Power Query 合并之后行数变多了」·「合并之后少了行」

第 3 题

你用「左外部」联接、按客户 ID 把一张 100 行的订单表和客户表合并。结果有 140 行。这说明什么?

  1. A合并失败了,把订单表复制了一份
  2. B客户表里有些客户 ID 对应多行,而左联接每匹配上一条就输出一行
  3. C左外部联接总会增加行数;用内部联接就还是 100 行
  4. D有 40 个订单没匹配到客户
看答案与解析

正确答案B. 客户表里有些客户 ID 对应多行,而左联接每匹配上一条就输出一行

🐱 左联接保证的是第一个表的每一行都活下来,而不是行数不变——第二个表里某个键有三行,那个订单就会回来三次。所以多出的 40 行意味着右表有重复键:客户表并不像你以为的那样按客户 ID 唯一。修法在上游:把客户表去重,或者在合并前先聚合成每个 ID 一行。每次合并后核一下行数,就是能抓住这个问题的习惯——因为结果在屏幕上看不出任何不对。

第 4 题

你把这个合并改成「内部」联接,结果降到 88 行。另外 12 行去哪了?

  1. A它们是重复行,被去掉了
  2. B它们没有匹配的客户 ID,而内部联接只保留两边都匹配上的行
  3. C它们没通过数据类型转换
  4. D内部联接为了性能会对数据抽样
看答案与解析

正确答案B. 它们没有匹配的客户 ID,而内部联接只保留两边都匹配上的行

🐱 内部联接只保留两边都存在的行,所以有 12 个订单引用了客户表里没有的客户 ID——孤儿记录,通常是一个值得知道、而不该被静默丢弃的数据质量问题。这正是「即使你预期能完全匹配上、也该先用左外部联接」的理由:没匹配上的行会带着空值回来,从而让问题可见,而不是让它消失。

继续练

Power Query — 常见问题

为什么我的 Power Query 在别人电脑上刷新失败?

因为查询里存的是你当初浏览选中那个文件的绝对路径,而那个路径在对方机器上不存在。加载好的结果会随工作簿一起走,所以在有人刷新之前表看起来完全正常。把路径放进单元格加载成参数,或者改用共享网络位置、SharePoint,让路径对每个人都一样。

「更改的类型」是什么步骤,为什么它会炸?

它是一个自动插入的步骤,里面存着一份显式的「列名 → 数据类型」清单。上游某列被改名或删除时,那一条就没法应用,刷新以「找不到列」失败。把自动插入的这一步删掉、等表的形状稳定后在最后统一设类型,能避掉大部分这类问题。

合并之后为什么行数变多了?

因为第二个表每个键有不止一行。左外部联接是每匹配上一条就输出一行,所以一个键匹配上三条就产生三行。合并前先把右表去重或聚合成每个键一行,并且每次合并后都核一下行数——结果在屏幕上看不出任何不对。

这里的左外部联接和内部联接有什么区别?

左外部保留第一个表的每一行,没匹配上的地方填空值。内部只保留两边都匹配上的行,所以没匹配上的行会静默消失。即使你预期能完全匹配上,通常也该先用左外部——因为那些空值会让孤儿记录可见,而不是把它们藏起来。

Power Query 会改动我的源数据吗?

不会。每一步转换都被记录成步骤、并在导入途中作用于一份副本;源文件只会被读取。这既是你可以随意删掉和重建步骤的原因,也是为什么真正修好一个数据问题通常意味着在源头修,而不是在查询里打补丁。