问题描述:
在数据分析工作中,常遇到结果展示的优化需求。需求如下: 查询在关注时间窗口下(7日)公司相同账户与不同交易对手账户之间的交易行为。 原本预计的展示结果为:
| 公司账户 | 公司信息 | 交易对手账户 | 交易对手信息 | 交易信息(日期等) |
|---|---|---|---|---|
| 66666666 | AAA | 99999991 | BBB1 | 2025-11-04 |
| 66666666 | AAA | 99999992 | BBB2 | 2025-11-06 |
| 66666666 | AAA | 99999993 | BBB3 | 2025-11-15 |
| 66666666 | AAA | 99999994 | BBB4 | 2025-11-22 |
| 88888888 | AAA | 99999995 | BBB5 | 2025-11-26 |
| 88888888 | AAA | 99999996 | BBB6 | 2025-12-01 |
| 88888888 | AAA | 99999997 | BBB7 | 2025-12-30 |
| 88888888 | AAA | 99999998 | BBB8 | 2026-01-01 |
| 88888888 | AAA | 99999999 | BBB9 | 2026-01-04 |
由于重复数据过多,不利于业务人员直观理解数据关联,经与业务人员讨论后决定调整为如下展示方式:
| 公司账户 | 公司信息 | 相关数据 |
|---|---|---|
| 66666666 | AAA | 交易对手账户:99999991 交易对手信息:BBB1 交易信息(日期等):2025-11-04 交易对手账户:99999992 交易对手信息:BBB2 交易信息(日期等):2025-11-06 |
| 66666666 | AAA | 交易对手账户:99999993 交易对手信息:BBB3 交易信息(日期等):2025-11-15 交易对手账户:99999994 交易对手信息:BBB4 交易信息(日期等):2025-11-22 |
| 88888888 | AAA | 交易对手账户:99999995 交易对手信息:BBB5 交易信息(日期等):2025-11-26 交易对手账户:99999996 交易对手信息:BBB6 交易信息(日期等):2025-12-01 |
| 88888888 | AAA | 交易对手账户:99999997 交易对手信息:BBB7 交易信息(日期等):2025-12-30 交易对手账户:99999998 交易对手信息:BBB8 交易信息(日期等):2026-01-01 交易对手账户:99999999 交易对手信息:BBB9 交易信息(日期等):2026-01-04 |
解决方案:
这样的展示方式就需要一个合适的聚合函数来进行数据内容汇总。 之前常使用Hive开发这种情况多用collect,但是本次使用的MySQL使用的时候发现没有这个函数。后面决定使用group_concat。 group_concat嵌套concat_ws可以很好的达到上面的效果:
,group_concat(concat_ws(''
,' 交易对手账户:',account
,' 交易对手信息:',account_info
,' 交易信息(日期等):',trade_date
) ORDER BY trade_date SEPARATOR ';\n') as 相关数据
参数调优
但是使用起来发现如果数据太长会有数据截断的问题。因此如果数据量比较大需要注意以下设置:
方式1:SET SESSION - 会话级(推荐)
-- 查看和设置 GROUP_CONCAT 相关参数
SHOW VARIABLES LIKE 'group_concat_max_len';
-- 临时设置最大长度(默认1024字节) 会话级配置
SET SESSION group_concat_max_len = 1000000;
-- 在查询中设置
SET @@group_concat_max_len = 1000000;
-- 特点:
-- ✓ 当前连接有效
-- ✓ 断开连接后自动还原
-- ✓ 不影响其他连接
-- ✓ 重启MySQL也会还原
方式2:SET GLOBAL - 全局级
-- 影响所有新会话(已存在的会话不受影响)
SET GLOBAL group_concat_max_len = 1000000;
-- 或者
SET @@global.group_concat_max_len = 1000000;
-- 特点:
-- ✓ 新连接会继承这个设置
-- ✓ 当前已存在的连接不变
-- ✗ 重启MySQL后还原(除非写入配置文件)
方式3:配置文件 - 永久
# my.cnf 或 my.ini
[mysqld]
group_concat_max_len = 1000000
-- 特点:
-- ✓ 永久生效
-- ✓ 重启MySQL也保持
-- ✓ 所有新连接都使用这个值
以上就是对于数据汇总展示的一个总结。希望能帮助到需要展示思路与需要聚合思路的朋友。
代替方案:
后面了解到也可以通过json的方式来展示这部分数据:
JSON_ARRAYAGG(
JSON_OBJECT(
'交易对手账户',account
,'交易对手信息',account_info
,'交易信息(日期等)',trade_date
)
) as 相关数据
不过问题是展示的字段顺序不可控。问题的原因查证后是因为JSON 标准决定的(对象键无序)。这个问题还没有解决的好办法,如果有大佬看到请多做指点。