如何破解 MySQL GROUP_CONCAT 以获取有限数量的行?

Posted

技术标签:

【中文标题】如何破解 MySQL GROUP_CONCAT 以获取有限数量的行?【英文标题】:How to hack MySQL GROUP_CONCAT to fetch a limited number of rows? 【发布时间】:2010-12-04 02:20:04 【问题描述】:

不知何故我需要这个功能,但 mysql 目前不支持它。

我正在使用GROUP_CONCAT(CONCAT(...)) 来生成类似 xml 的内容。

但是当大小超过限制时,xml就坏了!

所以我必须以某种方式让它只检索 5 行!

【问题讨论】:

增加my.cnf中的group_concat_max_len值 也许你可以在这里得到答案***.com/questions/3378324/…***.com/questions/23608464/group-concat-with-limit 【参考方案1】:

您可以使用用户变量模拟分区的row_number,然后限制行并应用group_concat:

考虑下表:

create table your_table (
    id int primary key autoincrement,
    category int,
    value int
);

和数据:

insert into your_table (category, value) 
values
(1,  1), (1,  2), (1,  3), (1,  4), (1,  5),
(2,  6), (2,  7), (2,  8), (2,  9), (2, 10),
(3, 11), (3, 12), (3, 13), (3, 14), (3, 15);

我们想要的是每个类别连接的前 3 个(按最新 id 顺序)值:

select category, 
    group_concat(value order by id desc) as value_con
from (
    select t.*,
        @rn := if(@category = category, @rn + 1, if(@category := category,1, 1)) as seqnum
    from your_table t
    cross join (select @category := null, @rn := 0) x
    order by t.category, t.id desc
    ) t
where seqnum <= 3
group by category;

输出:

category    value_con
1           5,4,3
2           10,9,8
3           15,14,13

这是一个demo。

【讨论】:

哇!因此可以将 where 子句放在子查询之外!这无意中解决了我的问题,即我有嵌套的子查询,而 MySQL 没有传递比一层更深的列引用。因此,当我将 where 子句移到子查询之外时,列引用位于第一级并且查询运行!嗯,我想如果我们用谷歌搜索足够长的时间,我们就能找到任何问题的答案!哈哈【参考方案2】:

对于那些你不能使用临时表的情况,我知道的最好的方法是选择一个模糊的分隔符,然后从所述字符的第一个实例开始截断。此示例使用 NUL 字符。

select substring_index(group_concat(field separator '\0'), '\0', 5) from table;

其中field 是字段名称,5 是结果数。

缺点是如果您的第一行包含该字符,它将是部分结果。

解决方法是将'\0' 替换为更长的随机字符串。

很高兴知道可以使用concat 替换field 以包含更多信息。

请记住,group_concat_max_len 默认为 1024 个字符,因此您应该考虑在全局范围内或在您的应用程序中更改它(如果您想要更多)。

【讨论】:

【参考方案3】:

我已经使用 SUBSTRING_INDEX 解决了这个问题。

例如:

SELECT SUBSTRING_INDEX(GROUP_CONCAT(Field1 SEPARATOR ','), ',', [# of elements to return])
FROM Table1;

【讨论】:

【参考方案4】:

使用临时表/子查询来限制结果?如果没有看到您的查询,就很难为该路线提供可靠的建议。

但是,您可能会发现group_concat_max_len 设置更有用。它控制GROUP_CONCAT 操作的最大长度,以字符串长度为单位。当您无法限制结果时,提高它以防止损坏GROUP_CONCATs。

【讨论】:

【参考方案5】:

查尔斯回答的一个例子:

基本:

SELECT GROUP_CONCAT( field ) FROM ( SELECT field FROM table LIMIT 200 )

扩展:

如果结果被缓冲区截断,CAST 会很有用:

SELECT CAST( GROUP_CONCAT( field ) AS CHAR(2048) ) FROM ( SELECT field FROM table LIMIT 200 )

【讨论】:

是的,它会起作用的。但是对于GROUP BY 的查询,它需要更复杂的构造。 在使用第一个查询时出现“每个派生表必须有自己的别名”的错误。为了解决这个问题,我将其更改为“ SELECT GROUP_CONCAT( field ) FROM ( SELECT field FROM table LIMIT 200 ) AS alias ” 感谢您的回答。【参考方案6】:

不是您的问题的真正答案,而是其他想要在 GROUP_CONCAT() 中使用 LIMIT 子句的人的参考:

feature-request 很久以前就提交给了 MySql 开发人员。尚未实现:-(

【讨论】:

以上是关于如何破解 MySQL GROUP_CONCAT 以获取有限数量的行?的主要内容,如果未能解决你的问题,请参考以下文章

如何正确使用不同的 group_concat - MYSQL

如何以不同的方式将 group_concat 添加到 hsqldb?

当我在查询中使用“GROUP_CONCAT”和“HAVING”时如何计算 MySQL 结果?

如何将 MySQL 子查询中的所有不同值选择到 group_concat 中?

如何使用 group_concat 和左连接计算 mysql 查询的结果

mysql group_concat函数详解