How to hack MySQL GROUP_CONCAT to fetch a limited

2019-01-07 20:15发布

I somehow need this feature,but MySQL doesn't support it at this moment.

I'm using GROUP_CONCAT(CONCAT(...)) to generate a xml-like stuff.

But when the size exceeds the limit,the xml is just broken!

So I have to somehow make it only retrieve 5 rows !

6条回答
做个烂人
2楼-- · 2019-01-07 20:39

An example for Charles answer:

basic:

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

extended:

CAST can be useful if result are truncated by buffer:

SELECT CAST( GROUP_CONCAT( field ) AS CHAR(2048) ) FROM ( SELECT field FROM table LIMIT 200 )
查看更多
Luminary・发光体
3楼-- · 2019-01-07 20:46

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():

A feature-request was filed long ago to MySql developers. Not yet implemented :-(

查看更多
ゆ 、 Hurt°
4楼-- · 2019-01-07 20:46

You can simulate the partitioned row_number using user variables and then limit rows and apply 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:

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.

查看更多
该账号已被封号
5楼-- · 2019-01-07 20:52

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.

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.

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.

It's good to know that field could be replaced to include more information using concat.

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.

查看更多
欢心
6楼-- · 2019-01-07 20:54

I've worked around this using SUBSTRING_INDEX.

For example:

SELECT SUBSTRING_INDEX(GROUP_CONCAT(Field1 SEPARATOR ','), ',', [# of elements to return])
FROM Table1;
查看更多
做个烂人
7楼-- · 2019-01-07 20:57

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. It controls the maximum length of a GROUP_CONCAT operation, in string length. Raise it to prevent broken GROUP_CONCATs, when you can't afford to limit results.

查看更多
登录 后发表回答