一、虚拟属性介绍
虚拟属性是将事件属性/用户属性通过SQL表达式进行二次加工,创建新的衍生属性,无需修改埋点即可扩展数据分析维度。
二、入口
菜单栏:数据管理-元数据管理-虚拟属性
三、创建虚拟事件
(一)事件属性
- 属性类型:选择您要创建的属性类型;
- 属性名称:定义该属性的名称;
- 属性别名:定义该属性的别名,可设置为更符合业务使用的名称;
- 所属事件:下拉选择该属性归属于哪个事件;
- SQL表达式:您可基于表信息,在输入框内输入SQL表达式;
(二)用户属性
- 属性类型:选择您要创建的属性类型;
- 属性名称:定义该属性的名称;
- 属性别名:定义该属性的别名,可设置为更符合业务使用的名称;
- SQL表达式:您可基于表信息,在输入框内输入SQL表达式;
- 输入信息后,点击保存即可;
四、管理虚拟属性
- 查看:点击虚拟属性名称,可查看详情;
- 启用/停用:功能用于限制是否可应用于分析功能(停用后不影响数据上报,仅是分析功能无法使用);
- 删除:删除后的虚拟属性无法再应用于分析,且已基于该属性生成的看板、报告等将不再显示该属性;
五、SQL规则说明
5.1 支持的SQL语法
5.1.1 算术运算符
+
加法-
减法*
乘法/
除法%
取模
示例:
event.transaction_price - event.cost_price
(event.price + event.tax) * event.quantity
5.1.2 比较运算符
=
等于!=
或<>
不等于>
大于<
小于>=
大于等于<=
小于等于
示例:
event.price > 1000
event.status = 'completed'
5.1.3 逻辑运算符
AND
逻辑与OR
逻辑或NOT
逻辑非
示例:
event.price > 1000 AND event.quantity > 10
event.status = 'completed' OR event.status = 'processing'
5.1.4 条件表达式 (CASE WHEN)
支持简单和复杂的条件判断。
简单条件:
CASE WHEN event.price > 1000 THEN 'high' ELSE 'low' END
多重条件:
CASE
WHEN event.price > 1000 AND event.quantity > 10 THEN 'bulk_discount'
WHEN event.price > 1000 THEN 'price_discount'
ELSE 'no_discount'
END
5.1.5 支持的函数
5.1.5.1 字符串函数
UPPER(str)
- 转换为大写LOWER(str)
- 转换为小写LENGTH(str)
- 获取字符串长度CONCAT(str1, str2, ...)
- 字符串拼接SUBSTRING(str, start, length)
- 字符串截取
示例:
UPPER(user.name)
CONCAT(user.first_name, ' ', user.last_name)
SUBSTRING(user.phone, 1, 3)
5.1.5.2 数学函数
ABS(num)
- 绝对值ROUND(num, scale)
- 四舍五入CEIL(num)
- 向上取整FLOOR(num)
- 向下取整
示例:
ABS(event.profit)
ROUND(event.profit_rate, 2)
CEIL(event.price / 100)
5.1.5.3 日期函数
NOW()
- 当前时间FROM_UNIXTIME(b_user_event_attr_50.分期时间)
- 时间戳转时间注意:FROM_UNIXTIME函数只接受10位(秒级)秒级时间戳,不支持13位(毫秒级),若入参为13位(毫秒级)时间戳,返回值为NULL
DATEDIFF(date1, date2)
- 日期差值(天数)DATE_FORMAT(date, pattern)
- 日期格式化
示例:
DATEDIFF(NOW(), user.created_at)
DATE_FORMAT(event.created_at, 'yyyy-MM-dd')
5.1.5.4 空值处理函数
COALESCE(val1, val2, ...)
- 返回第一个非空值
示例:
COALESCE(event.discount, 0)
5.2 不支持的类型
5.2.1 聚合函数
以下聚合函数不被支持,因为虚拟属性是基于单条记录计算的:
SUM()
- 求和AVG()
- 平均值COUNT()
- 计数MAX()
- 最大值MIN()
- 最小值GROUP_CONCAT()
- 分组拼接
5.2.2 json解析
get_json_string(json_str, path)
- 从 JSON 字符串中提取指定路径的字符串值。json_extract(json_str, path)
- 提取 JSON 中指定路径的值(返回类型为 JSON 格式的字符串)。parse_json(json_str)
- 将字符串解析为 JSON 类型(需配合 ->或 ->>操作符使用)。
如果在SQL表达式中使用这些函数,系统会抛出异常。
5.3 数据类型支持
5.3.1 输入数据类型
- 数值类型: int, long, float, double, BigDecimal
- 字符串类型: String
- 布尔类型: boolean, Boolean
- 日期类型: LocalDateTime, Date
- 空值: null
5.3.2 输出数据类型
计算结果会根据表达式类型自动确定:
- 算术运算结果为
BigDecimal
- 字符串函数结果为
String
- 比较运算结果为
Boolean
- 日期函数结果为
LocalDateTime
或Long
--支持的类型(type的可选值)
{
"field": "字段引用",
"constant": "常量值",
"operation": "操作运算", // arithmetic
"function": "函数调用", // math、sting、date、null_handling
"condition": "条件判断" // comparison
}
-- 每种类型支持的操作符(operator的可选值)
{
"arithmetic": ["add", "subtract", "multiply", "divide", "modulo"],
"comparison": ["equals", "not_equals", "greater_than", "less_than", "greater_equal", "less_equal"],
"logical": ["and", "or", "not"],
"string": ["concat", "substring", "length", "upper", "lower"],
"date": ["date_add", "date_diff", "date_format"],
"math": ["abs", "round", "ceil", "floor"],
"null_handling": ["coalesce", "nullif"]
}
5.4 字段引用规则
- 虚拟事件属性仅支持引用事件内属性, 用户属性仅支持用户属性
- 不支持嵌套:虚拟属性不支持嵌套,即不能引用其他虚拟属性。
字段命名规范
字段名必须以字母或下划线开头
- 可包含字母、数字、下划线和点号
- 区分大小写
- 若虚拟属性字段名和数据中字段名重复,实际数据保留虚拟属性
- 错误示例
// 聚合函数错误
"SUM(event.price)" // ❌ 不支持聚合函数
// 语法错误
"event.price + (" // ❌ 括号不匹配
// 字段错误
"event.nonexistent_field" // ❌ 字段不存在
示例1
event.transaction_price - event.cost_price
{
"type" : "operation",
"operator" : "subtract",
"operands" : [ {
"type" : "field",
"field" : "event.transaction_price"
}, {
"type" : "field",
"field" : "event.cost_price"
} ]
}
示例2
CASE
WHEN event.price > 1000 AND event.quantity > 10 THEN 'bulk_discount'
WHEN event.price > 1000 THEN 'price_discount'
ELSE 'no_discount'
END
{
"type" : "condition",
"conditions" : [ {
"condition" : {
"type" : "operation",
"operator" : "and",
"operands" : [ {
"type" : "operation",
"operator" : "greater_than",
"operands" : [ {
"type" : "field",
"field" : "event.price"
}, {
"type" : "constant",
"dataType" : "number",
"value" : 1000
} ]
}, {
"type" : "operation",
"operator" : "greater_than",
"operands" : [ {
"type" : "field",
"field" : "event.quantity"
}, {
"type" : "constant",
"dataType" : "number",
"value" : 10
} ]
} ]
},
"value" : {
"type" : "constant",
"dataType" : "string",
"value" : "bulk_discount"
}
}, {
"condition" : {
"type" : "operation",
"operator" : "greater_than",
"operands" : [ {
"type" : "field",
"field" : "event.price"
}, {
"type" : "constant",
"dataType" : "number",
"value" : 1000
} ]
},
"value" : {
"type" : "constant",
"dataType" : "string",
"value" : "price_discount"
}
} ],
"defaultValue" : {
"type" : "constant",
"dataType" : "string",
"value" : "no_discount"
}
}
5.5 常见问题(FAQ)
Q1: 为什么不支持聚合函数和拆分列函数?
A: 虚拟属性是基于单条记录进行计算的,而聚合函数和拆分列函数分别是要将数据多条合成一条以及一条拆分成多列,目前无法处理这两种情况,只支持一对一,类似理解为hive UDF 、UDAF 和 UDTF。
Q2: 如何处理除零错误?
A: 系统会自动抛出ArithmeticException
,建议在表达式中使用条件判断避免除零:
CASE WHEN order.quantity = 0 THEN 0 ELSE order.total / order.quantity END
Q3: 支持哪些日期格式?
A: 系统使用LocalDateTime
处理日期,支持ISO格式。在DATE_FORMAT
函数中使用Java的日期格式模式。
Q4: 字段名包含特殊字符怎么办?
A: 目前系统支持字母、数字、下划线和点号。如果字段名包含其他特殊字符,建议在数据预处理时进行字段重命名。
Q5: 如何处理null值?
A:
- 在算术运算中,null会被转换为0
- 在字符串运算中,null会被转换为空字符串
- 使用
COALESCE
函数显式处理null值 - 使用
NULLIF
函数将特定值转换为null