RDS MySQL函数group_concat相关问题

本文介绍RDS MySQL函数group_concat相关问题。

group_concat返回结果的长度

函数group_concat返回结果的长度受参数group_concat_max_len控制,默认值为1024,即默认返回1024字节长度结果。

参数名称

默认值

取值范围

说明

group_concat_max_len

1024

4-1844674407370954752

group_concat函数返回结果的最大长度,单位:Byte。

说明

您可以设置参数group_concat_max_len在全局生效或会话级别生效:

  • 全局生效:在控制台的参数设置页面修改。

  • 会话级别生效:

    set group_concat_max_len=90; -- 设置当前会话 group_concat_max_len 为 90 字节
    
    show variables like 'group_concat_max_len'; -- 查看当前会话的 group_concat_max_len 值
    
    select group_concat(distinct concat_ws(' ', t1.col0, t1.col2, t1.col3, t1.col4) separator "---")
    from grp_con_test t1, grp_con_test t2 \G  -- 查询结果
    
    select length(group_concat(distinct concat_ws(' ', t1.col0, t1.col2, t1.col3, t1.col4) separator "---"))
    from grp_con_test t1, grp_con_test t2 \G  -- 查询结果的长度

    当前会话生效

group_concat(distinct) 去除重复数据失效的处理

失效原因

当设置group_concat_max_len为较大值时,使用group_concat(distinct)去除结果中的重复数据,会出现失效的情况,例如:

select group_concat(distinct concat_ws(' ', t1.col0, t1.col2, t1.col3, t1.col4) separator "---")
from grp_con_test t1, grp_con_test t2 \G -- 查询结果

数据重复

可以看到,结果中出现了多个重复值。出现这个问题的原因当group_concat返回结果集比较大,会出现内存临时表无法承载全部结果集数据,进而会使用磁盘临时表;而group_concat在使用磁盘临时表时会触发BUG导致无法去除重复数据。

解决方法

调整tmp_table_size参数设置,增大内存临时表的最大尺寸,命令如下:

set tmp_table_size=1*1024*1024 -- 设置当前会话 tmp_table_size 为 1 MB
show variables like 'tmp_table_size' -- 查看当前会话 tmp_table_size 的设置
select group_concat(distinct concat_ws(' ', t1.col0, t1.col2, t1.col3, t1.col4) separator "---")
from grp_con_test t1, grp_con_test t2 \G
说明

您也可以在控制台的参数设置页面修改参数tmp_table_size

group_concat和concat结合使用返回异常

异常原因

group_concat和concat结合使用某些情况下会出现返回BLOB字段类型的情况,例如:

select concat('{' ,group_concat(concat('\"payMoney' ,t.signature ,'\":' ,ifnull(t.money,0))) ,'}') payType
from my_money t
where cash_id='989898989898998898'
group by cash_id;

返回BLOB字段

这是由于函数concat按字节返回结果,如果concat的输入有多种类型,其结果是不可预期的。

解决方法

通过cast函数进行约束,使concat返回结果为字符串类型,将上面示例修改为:

select concat('{' ,cast(group_concat(concat('\"payMoney' ,t.signature ,'\":' ,ifnull(t.money,0))) as char) ,'}') payType
from my_money y t
where cash_id='989898989898998898'
group by cash_id;