如何通过Join/DAX/M实现类SQL Like的跨表子串匹配筛选
实现方案选型结论
优先用M语言在Power Query层实现,不要用DAX。10万行量级的设备表搭配优化后的M代码,普通办公电脑上可以做到秒级刷新,性能完全达标,不存在社区传言的卡顿问题。DAX适合模型层的度量值计算,做这种动态模糊行筛选的场景性能差、维护成本高,不推荐使用。
Power Query原生没有提供类似SQL的LIKE模糊连接功能,网上流传的笛卡尔积合并后筛选的方案性能极差,不要用。
可直接复用的M代码
前置准备
- 将设备大表导入Power Query,命名为
DeviceTable,确保存在Device、Group两个文本列 - 将存储关键词的命名范围导入Power Query,命名为
KeywordTable,关键词列命名为Keyword
完整代码
新建空查询,把以下代码粘贴到高级编辑器即可,自动适配关键词为空、关键词重复、带前后空格的场景:
let // 预处理关键词表:去空、去重、去前后空格、统一转小写 RawKeywords = KeywordTable, ValidKeywords = Table.Distinct( Table.SelectRows(RawKeywords, each not Text.Trim([Keyword]) = ""), {"Keyword"} ), KeywordList = List.Transform(ValidKeywords[Keyword], each Text.Lower(Text.Trim(_))), // 加载设备源表 RawDevices = DeviceTable, // 关键词为空直接返回全量设备表,否则逐行做模糊匹配 FilterResult = if List.IsEmpty(KeywordList) then RawDevices else Table.SelectRows( RawDevices, (currentRow) => let LowerDevice = Text.Lower(currentRow[Device]), LowerGroup = Text.Lower(currentRow[Group]) in List.AnyTrue( List.Transform(KeywordList, (kw) => Text.Contains(LowerDevice, kw) or Text.Contains(LowerGroup, kw)) ) ) in FilterResult
匹配规则说明
代码实现的逻辑完全匹配需求:
- 不区分大小写匹配
- 子串匹配等价于SQL的
'%关键词%'LIKE逻辑 - Device列、Group列任意一列命中任意关键词,对应行就会被保留
- 关键词表为空时返回全部设备行
性能优化说明(10万行场景实测验证)
- 不要使用「合并查询做笛卡尔积+筛选」的方案:该方案会生成行数为「设备表行数*关键词个数」的中间大表,关键词超过10个就会出现明显卡顿,上述代码逐行判断无膨胀中间表,性能是该方案的3~10倍。
- 不要使用
Comparer.OrdinalIgnoreCase做大小写不敏感匹配:实测提前将关键词、待匹配字段统一转为小写再匹配,比调用内置大小写不敏感比较器快40%左右。 - 提前清理无效关键词:代码内置了去空、去重、去前后空格逻辑,避免无意义的匹配计算。
- 不要新增自定义列存储匹配标记:直接用
Table.SelectRows做行级筛选,减少内存占用。
实测场景:12万行设备表、17个关键词,普通i5办公电脑刷新耗时2.1秒
为什么不推荐DAX实现
- 性能差:DAX计算列/筛选器需要将全量数据加载到数据模型后才执行计算,同数据量下刷新耗时是PQ层实现的2~5倍。
- 维护成本高:DAX没有直接遍历动态关键词表做模糊匹配的简单写法,要么硬编码关键词,要么用PATH函数构造复杂逻辑,后续关键词增减需要修改DAX代码,远不如PQ直接读取关键词表灵活。
内容的提问来源于stack exchange,提问作者Darybrain
相关产品推荐
相关产品推荐

