高级数据映射器用法
在深入了解数据映射器的高级功能之前,先简要回顾一下基本功能。
数据映射器配置
Section titled “数据映射器配置”数据映射器用于将源数据中的列映射到目标数据表。
检查和填充映射器
Section titled “检查和填充映射器”使用检查源菜单按钮可以通过更多方式将列从源映射到目标:
- 填充两个映射表:将源数据表中的所有值传播到目标数据表。这是默认行为。
- 仅填充源映射表:仅映射源数据表中的所有值。当源列结构发生变化而需要修改现有工作流时,此选项很有用。
- 仅填充目标映射表:仅将所有值传播到目标数据表。
如果上述源列和目标列选项还不够,还可以通过以下几种方式将其他列添加到目标数据表中:
- 全部传播会将所有源列插入目标数据表,无论它们是否已存在。
- 传播所选项仅插入所选的源列。
- 在目标侧右键单击并选择插入行,可在当前所选行的正上方插入一行。
- 在目标侧右键单击并选择追加行,可在目标数据表的底部(最右侧)插入一行。
若要从目标数据表中删除列,请选择所需的列,然后右键单击并选择删除。
若要重新排列目标数据表中的列,请选择所需的列。可以使用以下任一方式:
- 批量移动箭头:使用右上角的箭头选择所需的移动选项
- 上下文菜单:右键单击并选择移到顶部、上移、下移或移到底部。
将结果缩减为仅非重复记录
Section titled “将结果缩减为仅非重复记录”若只返回非重复的结果,请选择非重复菜单选项。这会为源中的每一列显示一组复选框。只需勾选相应列旁边的复选框,即可仅返回非重复的结果。
若要聚合结果,请选择汇总菜单选项。这会为目标数据表中的每一列显示一组选择框。请为每一列选择合适的汇总方法。
若要聚合结果,请选择汇总菜单选项。这会为目标数据表中的每一列显示一组选择框。可使用以下汇总选项:
| 函数 | 说明 |
|---|---|
| 分组依据 | 按值对结果分组 |
| 计数 | 组中非空观测值的数量 |
| 计数(含空值) | 组中观测值的数量 |
| 合计 | 组中值的总和 |
| 平均值 | 组中值的平均值 |
| 中位数 | 组中值的中位数 |
| 众数 | 组中值的众数 |
| 最小值 | 组中值的最小值 |
| 最大值 | 组中值的最大值 |
| 第一个值 | 按排序顺序,组中值的第一个值 |
| 最后一个值 | 按排序顺序,组中值的最后一个值 |
| 标准差 | 组内的无偏标准差 |
| 样本标准差 | 组内的样本标准差 |
| 总体标准差 | 组内的总体标准差 |
| 方差 | 组内的无偏方差 |
| 样本方差 | 组内的样本方差 |
| 总体方差 | 组内的总体方差 |
| 高级非分组依据 | 使用窗口函数时的特殊聚合选择 |
请为列选择合适的汇总方法。
面向 REST 和 AI 助手的聚合键
Section titled “面向 REST 和 AI 助手的聚合键”通过 REST API 或 AI 助手设置步骤时,每个目标列都在 agg 中携带其汇总方式,步骤的 aggregation_type 选择相同的选项。每个带数据映射器的步骤都接受以下值:
| 键 | 汇总方式 |
|---|---|
group |
分组依据 |
dont_group |
高级非分组依据:该列既不分组也不聚合,适用于自行聚合或使用窗口函数的表达式 |
count |
组中非空观测值的计数 |
count_null |
含空值的计数 |
count_distinct |
组中非重复值的计数 |
sum |
合计 |
avg |
平均值 |
median |
中位数 |
min |
最小值 |
max |
最大值 |
stddev |
标准差 |
stddev_samp |
样本标准差 |
stddev_pop |
总体标准差 |
variance |
方差 |
var_samp |
样本方差 |
每个目标列都可以带有 sort:asc、desc 或 none,也可以是对象 {ascending, order}。ascending 为 true 或 false。order 是一个整数,用于设置排序键的优先级:带有 order 的列优先排序,数字最小的最先,其余已排序的列随后按列位置排序。
使用窗口函数时,请选择高级非分组依据作为聚合方法。由于窗口函数本身已包含聚合,因此必须使用这一特殊选项。
在常量列中指定值,将覆盖源列的值(如果已指定),并用指定的常量值填充该列。
源、常量和表达式同时存在
Section titled “源、常量和表达式同时存在”目标列的值取自您填写的以下内容之一,优先级依次为:常量优先,其次是表达式,最后是源列。
因此,自行计算值的列不需要源。对于常量或表达式,请将其留空:常量或表达式已经说明了值是什么,与之并存的源会被忽略。当您将列从传入数据直接映射过来、重命名它,或在此过程中转换其类型时,再填写源。
表达式通过 get_column(table, 'Column Name') 按名称读取传入的列,而不是通过源单元格。
数据映射器提供了便捷的点选式清理器功能,可对列中的数据应用转换。
清理操作包括以下类别:
- 文本裁剪
- 文本格式设置
- 文本转换
- 与 NULL 值互相转换
- 数字格式
- 日期解析
清理器的选择结果会被转换为一个合并的表达式,可在表达式信息中查看。
数据映射器中的表达式是 PlaidCloud 中最强大、最灵活的概念之一。它们提供近乎无限的灵活性,即使在极大的数据上也具有出色的性能。
表达式使用 Python SQLAlchemy 语法编写,并附带 PlaidCloud 中提供的一些额外辅助函数。 这使 PlaidCloud 能够直接公开底层数据仓库(例如 Greenplum、SAP HANA、Redshift 等)的全部功能。此外,还有许多公开资源提供了 SQLAlchemy 操作用法的速查参考。通过使用标准的 SQLAlchemy 语法,PlaidCloud 避免了再创造一种领域专用语法这一常见陷阱。
双击该列的表达式单元格即可打开表达式编辑器。打开后,左侧显示列的列表,右侧显示丰富的函数库。
虽然完全可以直接在编辑器中键入表达式,但通常更容易的做法是先使用点选式的函数和列选择来入手。函数库包括以下分组:
- 条件
- 列特定条件
- 转换
- 日期
- 数学
- 文本
- 汇总
- 窗口函数运算
- 数组
- JSON
- PostGIS(地理空间)
- 三角函数
完成表达式后,请保存表达式,使其应用于该列。
可在表达式区域查看示例和表达式函数。
转换为 Float
Section titled “转换为 Float”在所有数据仓库上,cast(x, Float) 都会返回 64 位双精度数,因此像 1225541207.71 这样的金额会保留每一位数字。在 StarRocks 上,现在会应用到 Float 的转换(此前会被跳过);在 Databend 上,它是双精度而不是单精度。PlaidCloud 根据浮点数据创建的 Float 列同样是双精度。已有单精度列的表,在下次由步骤使用覆盖重建时会变为双精度。
在 StarRocks 上:
- 转换为大整数可容纳超过约 21 亿的值。
- 未指定精度的
Numeric转换会保留小数(最多 10 位),而不是四舍五入为整数。 - 会应用到 JSON 的转换。
在所有数据仓库上,无法转换的值(例如将非数字文本转换为数字)会变为 null,而不是使步骤停止。
通过表达式读取另一个表
Section titled “通过表达式读取另一个表”sqlalchemy.literal_column 会将一段 SQL 原样传递给数据仓库,并且只接受单个值:列、计算、CASE、函数调用、转换或窗口函数。包含子查询((SELECT ... FROM ...))的 literal_column 会被拒绝,因为子查询会访问步骤从未声明的表。
本节中的规则适用于编写表达式的任何位置:此处的映射器、步骤的筛选器,以及在其他位置组装并发送到平台的查询。它们会在保存步骤时以及将表达式转换为 SQL 时再次检查。
请改用 sqlalchemy.select(...) 构建子查询:需要在列中得到单个值时使用 .scalar_subquery(),需要从中选择数据时使用 .subquery():
# Refusedsqlalchemy.literal_column('(SELECT rate FROM fx WHERE fx.cc = t.cc)')
# Supported — a single value in a columnsqlalchemy.select(fx.c.rate).where(fx.c.cc == t.c.cc).scalar_subquery()
# Supported — a table to select fromsqlalchemy.select(fx.c.rate).subquery()为顶层 OR 加括号
Section titled “为顶层 OR 加括号”最外层运算符为 OR 的 literal_column 同样会被拒绝。PlaidCloud 会原样传递文本,因此在其后添加的条件只会绑定到其中一半:a OR b 后面跟 AND region = 'East' 会被解读为 a OR (b AND region = 'East'),本应排除的行会被返回。
加上括号即可像以前一样工作:
# Refusedsqlalchemy.literal_column("status = 'open' OR status = 'pending'")
# Supportedsqlalchemy.literal_column("(status = 'open' OR status = 'pending')")表达式内部任意位置的析取(例如在 CASE 中,或已加括号)不受影响。
无论是否加括号,XOR 在出现的任何位置都会被拒绝:各数据仓库对其绑定优先级的处理不一致,因此不存在在所有位置都安全的解读。请改为写成 (a AND NOT b) OR (NOT a AND b)。
带有注释的 literal_column 出于同样的原因也会被拒绝:注释会延伸到语句末尾,因此会抹去 PlaidCloud 在您的表达式之后添加的任何内容,而不仅仅是您所写的内容。
-- 在会波及语句其余部分的位置会被拒绝。# 在文本中的任何位置都会被拒绝,没有例外,包括在带引号的字符串内,也包括 Postgres 的 #> 和 #>> JSON 路径运算符:
# Refusedsqlalchemy.literal_column("attrs #> '{a,b}'")sqlalchemy.literal_column("code || '#'")在 StarRocks 等兼容 MySQL 的数据仓库上,# 会开启注释;而且编写表达式时,PlaidCloud 并不知道将由哪个数据仓库运行它,因此文本中没有任何位置是可靠安全的,在一个引擎看来带引号的 #,在另一个引擎看来却是注释的开头。如果需要将该字符作为数据,请将其作为值传入:
# Supportedsqlalchemy.func.concat(table.code, sqlalchemy.literal('#')).op('...') 中同样会拒绝这两种写法。
literal_column 的其他常规用法不受影响:literal_column('current_date')、literal_column("CASE WHEN amount > 0 THEN 'p' ELSE 'n' END") 和 func.count() 都和以前一样可用。包含空格、点或引号的列名也不受影响,数据仓库会为您加上引号。