Metabase Concat 表达式完全指南:列拼接、类型转换与 SQL/Spreadsheet/Python 等价实现
2026/9/12 14:41:38 网站建设 项目流程

Metabase Concat 表达式完全指南:列拼接、类型转换与 SQL/Spreadsheet/Python 等价实现

【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase

导读

concat是 Metabase 自定义表达式(Custom Expressions)中最常用的字符串函数之一,用于将两个及以上列或值拼接为一个字符串,典型场景包括合并"城市 + 国家"生成完整地址、拼接订单号前缀、组合姓名与称谓等。本文以官方文档docs/questions/query-builder/expressions/concat.md为核心骨架,结合 Metabase 开源仓库中 MBQL(Metabase BI Query Language)的 schema 定义、查询转换器与 SQL 驱动实现,完整讲解concat的语法、参数规则、非字符串列的自动类型转换行为、可接受数据类型,以及它与 SQLCONCAT、ExcelCONCATENATE、Python 字符串相加的等价写法。读完本文,你将能在 Metabase 查询构建器中熟练使用concat生成自定义列,并理解其底层执行机制。

什么是 concat

concat(拼接)将两个或多个列(字段)或值按顺序连接在一起,并返回一个字符串。它是查询构建器表达式编辑器中"字符串函数"一族的代表成员,与substringregexextractreplace等函数一起,在metabase.lib.schema.expression.string中被统一定义。

从 MBQL 的 schema 定义看,concat是一个"catn"(concat-and)类型的子句,其返回类型被固定为:type/Text,参数由[:args [:repeat {:min 2} [:schema [:ref ::expression/expression]]]]约束——即至少需要两个参数,每个参数可以是任意表达式(列引用、字面量或嵌套函数):

(mbql-clause/define-catn-mbql-clause :concat :- :type/Text [:args [:repeat {:min 2} [:schema [:ref ::expression/expression]]]])

该定义位于 src/metabase/lib/schema/expression/string.cljc,是前端表达式校验与后端 MBQL 解析共享的唯一事实来源(.cljc双平台文件)。这意味着无论你在查询构建器中书写还是通过 API 提交 MBQL,concat的参数数量与类型都会先经过这层 schema 校验。

语法

concat(value1, value2, ...)
  • value1value2… 可以是列引用字面值
  • Metabase 会在拼接前将非字符串类型的列自动转换为字符串
  • 表达式的结果始终是字符串,无论传入值的类型如何;
  • 参数之间按书写顺序依次连接,不自动插入任何分隔符——需要分隔符(如逗号、空格)时,必须作为独立的字符串参数显式写出。

列引用使用方括号语法,例如[City][Country];字符串字面量使用双引号,例如" is in "。关于列引用、连接表列[ConnectedTableName.Column]以及引用已保存的指标/分段的通用规则,可参阅 自定义表达式总览。

示例

表达式结果
concat("Vienna", "Austria")"ViennaAustria"
concat("Vienna", " is in " ,"Austria")"Vienna is in Austria"
concat([City], " is in " ,[Country])"Vienna is in Austria"

第一行演示了纯字面量拼接(注意没有自动加空格);第二行演示了用字面量插入分隔文本;第三行演示了实战中最常见的形态——拼接两个列并在中间插入分隔符。

非字符串列:Metabase 使用未格式化(raw)值

这是使用concat时最容易踩的坑:当你在concat中使用非字符串列时,Metabase会忽略你在列上配置的任何格式化(Formatting)设置,直接使用底层数据库返回的原始值进行转换拼接。

例如,你在表格结果中把一个数字列格式化为只显示两位小数,concat的结果仍会包含原始数据里(如果有的话)更多的小数位。

格式化后的显示原始值concat("Result:", " ", [Value])
KittenKittenResult: Kitten
1717Result: 17
31.2531.24823945Result: 31.24823945
42%0.42Result: 0.42
January 1, 20242025-02-11 21:40:27.892Result: 31.24823945

要点:

  • 数字31.25的格式化显示与concat结果不一致,因为拼接使用的是31.24823945这个原始值;
  • 百分比42%在拼接结果中变成0.42(原始的比值小数);
  • 日期列也是如此——即使显示为January 1, 2024,拼接输出的是完整时间戳2025-02-11 21:40:27.892

因此,若你需要"格式化后"的文本效果(如保留两位小数、百分比符号、特定日期格式),应在拼接前先用format相关的字符串函数或对原始值做预处理,而不是依赖列的展示格式化。列格式化本身的管理方式见 数据建模 - 格式化。

可接受的数据类型

数据类型是否可用于concat
String
Number
Timestamp
Boolean
JSON

所有非字符串类型都会被转换为字符串;无论传给concat的值是什么类型,结果始终是字符串。这一点与 schema 定义中返回类型固定为:type/Text完全一致:类型系统在 MBQL 层面就保证了concat的输出一定是文本。

从查询转换链路看,这一"结果必为字符串"的约束还体现在 src/metabase/lib/convert.cljc——该文件将:concat:substring:replace:regex-match-first:split-part:collate等字符串算子归为一类进行统一转换处理,确保这些表达式在进入 SQL 编译阶段前保持一致的语义。

在查询构建器中使用 concat

concat最常见的用途是在**自定义列(Custom Column)**中创建新的文本字段:

  1. 在查询构建器中点击自定义列(Custom Column)
  2. 在表达式编辑器中输入,例如concat([City], ", ", [Country])
  3. 为新列命名(如Location),点击Done完成。

concat也可以作为**过滤器(Filter)汇总(Summarize)**表达式的一部分(虽然过滤器场景通常配合contains等谓词使用)。关于表达式编辑器的完整操作方式(函数浏览器、自动格式化、聚合与函数的区别等),参见 自定义表达式文档。

快捷操作:合并列(Combine Columns)

值得一提的是,Metabase 还为字符串列提供了Combine Columns(合并列)的快捷操作:点击列头时,如果当前列是字符串列,会触发:drill-thru/combine-columns动作,底层自动生成一个concat表达式,把点击的列与一个或多个"分隔符 + 列"对拼接起来。该功能在 src/metabase/lib/drill_thru/combine_columns.cljc 中实现:

  • 触发条件:列存在、value为空(非聚合场景)、当前 stage 是 MBQL stage、且该列的语义类型为字符串;
  • 效果:等价于手动写出concat([Column], [separator], [nextColumn], ...)的自定义表达式。

这意味着大多数"合并两列"的需求你甚至不需要手写表达式,直接点击列头选择 Combine Columns 即可,生成的结果就是一个concat表达式。

底层执行:从 MBQL 到 SQL

当你在查询构建器中写完concat([City], ", ", [Country])并运行后,Metabase 会把它编译成针对底层数据库的 SQL。以关系型数据库为例,最终执行的语句形如:

SELECT CONCAT(City, ', ', Country) AS "Location" FROM richard_linklater_films;

在 SQL 驱动的查询处理器 src/metabase/driver/sql/query_processor.clj 中,MBQL 的:concat子句会被编译为 HoneySQL 形式的[:concat ...]表达式,再交由具体驱动生成各数据库方言的拼接语法(如 MySQL/PostgreSQL 的CONCAT、SQLite 的||等)。同一个concat表达式在 generate-pattern 等内部逻辑中也被复用——例如实现contains/starts-with/ends-with这类LIKE匹配时,非字面量模式会通过[:concat pre arg post]构造匹配串,可见concat是 SQL 后端的基础算子。

因此可以推断:concat的拼接工作在数据库端完成,Metabase 的自动类型转换最终表现为 SQL 中的隐式/显式字符串转换,这也是为什么展示格式化不会生效——格式化是前端展示层的行为,而拼接发生在 SQL 层。

与其他工具函数的等价实现

SQL

如果你的数据存在关系型数据库中,notebook 编辑器生成的查询最终都会转成 SQL。以下 SQL:

SELECT CONCAT(City, ", ", Country) AS "Location" FROM richard_linklater_films;

等价于 Metabase 表达式:

concat([City], ", ", [Country])

注意:不同数据库的拼接语法略有差异(MySQL/PostgreSQL/SQL Server 使用CONCAT,SQLite/PostgreSQL 也支持||运算符),Metabase 驱动层会屏蔽这些差异,让你始终用统一的concat书写。

Spreadsheets(电子表格)

如果样本数据在电子表格中,"City" 在 A 列、"Country" 在 B 列,可以用公式在 C 列生成 "Location":

=CONCATENATE(A2, ", ", B2)

等价于 Metabase 表达式:

concat([City], ", ", [Country])

(Excel/Google Sheets 中的&运算符、CONCAT函数同样可达到类似效果,Metabase 的concat语义与它们一致:按参数顺序拼接、不自动加分隔符。)

Python

假设样本数据在名为df的 DataFrame 中:

df["Location"] = df["City"] + ", " + df["Country"]

等价于 Metabase 表达式:

concat([City], ", ", [Country])

Metabase 表达式与编程语言写法的共同点是:所有操作都是按行进行的向量化操作——对每一行独立计算拼接结果,这正是表达式(Functions)与聚合(Aggregations)的本质区别,详见 自定义表达式文档。

常见问题与最佳实践

  • 不要依赖自动分隔符concat不会自动插入空格或逗号。concat("Vienna", "Austria")的结果是ViennaAustria。始终把分隔符写成独立的字符串参数。
  • 分隔符用字面量:分隔符属于固定文本,应写成双引号字符串字面量,如", "" - "" "
  • 注意类型转换语义:数字、布尔、时间戳、JSON 都会转换为原始字符串。若需要格式化后的文本(两位小数、百分比符号、YYYY-MM-DD日期),先格式化再拼接。
  • 参数至少两个:MBQL schema 强制要求concat至少 2 个参数;单参数拼接没有意义,可考虑直接引用列或使用其他函数。
  • 空值与拼接:当参与拼接的列含NULL时,不同数据库的行为可能不同(有的数据库CONCAT(NULL, ...)直接返回NULL)。若需要将空值视为空字符串,可结合coalesce使用,例如concat(coalesce([City], ""), ", ", coalesce([Country], ""))
  • 优先使用 Combine Columns 快捷操作:仅拼接现有字符串列时,点击列头选择 Combine Columns 即可自动生成concat表达式,减少手写出错的可能。

延伸阅读

  • 自定义表达式文档(总览) —— 表达式编辑器、函数浏览器、聚合与函数的区别
  • Substring(子串截取) —— 与concat搭配的字符串处理函数
  • Coalesce(空值兜底) —— 处理拼接中的 NULL 值
  • 数据建模 - 格式化 —— 了解列格式化与concat原始值行为的关系
  • 表达式 schema 定义 ——concat在 MBQL 层的最小参数与返回类型约束
  • 合并列 drill-thru 实现 —— Combine Columns 快捷操作的底层原理

【免费下载链接】metabaseThe easy-to-use open source Business Intelligence and Embedded Analytics tool that lets everyone work with data :bar_chart:项目地址: https://gitcode.com/GitHub_Trending/me/metabase

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询