简体   繁体   English

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

[英]How to hack MySQL GROUP_CONCAT to fetch a limited number of rows?

I somehow need this feature,but MySQL doesn't support it at this moment. 我不知何故需要这个功能,但MySQL目前不支持它。

I'm using GROUP_CONCAT(CONCAT(...)) to generate a xml-like stuff. 我正在使用GROUP_CONCAT(CONCAT(...))来生成类似xml的东西。

But when the size exceeds the limit,the xml is just broken! 但是当大小超过限制时,xml就会被破坏!

So I have to somehow make it only retrieve 5 rows ! 所以我必须以某种方式使它只检索5行!

I've worked around this using SUBSTRING_INDEX . 我使用SUBSTRING_INDEX解决了这个问题。

For example: 例如:

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

An example for Charles answer: Charles回答的一个例子:

basic: 基本:

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

extended: 扩展:

CAST can be useful if result are truncated by buffer: 如果结果被缓冲区截断,则CAST非常有用:

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

Use a temporary table / subquery to limit results? 使用临时表/子查询来限制结果? Without seeing your query, it'll be hard to give solid advice for that route. 如果没有看到您的查询,就很难为该路线提供可靠的建议。

However, you may find the group_concat_max_len setting to be more useful. 但是,您可能会发现group_concat_max_len设置更有用。 It controls the maximum length of a GROUP_CONCAT operation, in string length. 它以字符串长度控制GROUP_CONCAT操作的最大长度。 Raise it to prevent broken GROUP_CONCAT s, when you can't afford to limit results. 当你无法限制结果时,提高它以防止GROUP_CONCAT损坏。

Not really an answer to your question but a ref for other people who also would want to use a LIMIT clause in GROUP_CONCAT(): 对你的问题不是一个真正的答案,而是为那些也希望在GROUP_CONCAT()中使用LIMIT子句的其他人提供的参考:

A feature-request was filed long ago to MySql developers. 很久以前就向MySql开发人员提交了一个功能请求 Not yet implemented :-( 尚未实现 :-(

For those cases where you cannot use a temp table, The best way I know of is to select an obscure separator and then truncate starting at the first instance of said character. 对于那些你不能使用临时表的情况,我所知道的最好的方法是选择一个模糊的分隔符,然后从所述字符的第一个实例开始截断。 This example uses the NUL character. 此示例使用NUL字符。

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

Where field is the name of the field, 5 is the number of results. where fieldfield的名称, 5是结果的数量。

The drawback is if your first row contains that character, it will be a partial result. 缺点是如果你的第一行包含该字符,它将是部分结果。

A workaround would be to replace '\\0' with a longer random string. 解决方法是用更长的随机字符串替换'\\0'

It's good to know that field could be replaced to include more information using concat . 很高兴知道可以使用concat替换field以包含更多信息。

Keep in mind the group_concat_max_len defaults to 1024 characters, so you should look into changing that either globally or within your application if you want more than that. 请记住, group_concat_max_len默认为1024个字符,因此如果您想要更多,请考虑全局或在应用程序中更改它。

You can simulate the partitioned row_number using user variables and then limit rows and apply group_concat: 您可以使用用户变量模拟分区的row_number,然后限制行并应用group_concat:

Consider the following table: 请考虑下表:

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

and data: 和数据:

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);

And we want is top 3 (in order of latest id) value per category concatenated: 我们想要的是每个类别连接的前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;

Output: 输出:

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

Here is a demo of this. 这是一个演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM