如何在MySQL的CONCAT中使用GROUP_CONCAT


117

如果我在MySQL中有一个包含以下数据的表:

id       Name       Value
1          A          4
1          A          5
1          B          8
2          C          9

如何将其转换为以下格式?

id         Column
1          A:4,5,B:8
2          C:9


我想我必须使用GROUP_CONCAT。但是我不确定它是如何工作的。

Answers:


160
select id, group_concat(`Name` separator ',') as `ColumnName`
from
(
  select 
    id, 
    concat(`Name`, ':', group_concat(`Value` separator ',')) as `Name`
  from mytbl
  group by 
    id, 
    `Name`
) tbl
group by id;

您可以在此处看到它的实现:Sql Fiddle演示。正是您所需要的。

分两步更新拆分。首先,我们得到一个表,该表具有针对唯一[Name,id]的所有值(用逗号分隔)。然后,从获得的表格中我们得到的所有名称和值作为对每一个唯一的ID的单个值在这里看到这个解释SQL小提琴演示(向下滚动,因为它有两个结果集)

编辑阅读问题时出现错误,我仅按ID分组。但是,如果需要两个group_contacts(值将按名称和ID分组,然后按ID整体分组)。先前的答案是

select 
id,group_concat(concat(`name`,':',`value`) separator ',')
as Result from mytbl group by id

您可以在此处看到它的实现:SQL Fiddle演示


这不能满足Biswa的要求。
eisberg

3
我认为警告人们使用仅一种分隔符可能是不利的,这一点很重要。我建议将“名称”分隔符设置为分号(;),值分隔符可以保留为逗号(,)
Fandi Susanto

4
另请注意,这GROUP_CONCAT可能会无提示地将其输出截断为group_concat_max_lenSET group_concat_max_len=...会有所帮助,但是无论如何都要检查返回的(byte?)长度是否小于,这是一个好主意group_concat_max_len
tuomassalo

2
还要注意,group_concat遇到单个NULL值,它将忽略包含它的整行。我在这里的第二个警告中解决此问题
MatrixManAtYrService

1
如果有人在答案中给出的SQL Fiddle链接遇到问题。工作小提琴在这里:sqlfiddle.com/#
Hitesh,

21

尝试:

CREATE TABLE test (
  ID INTEGER,
  NAME VARCHAR (50),
  VALUE INTEGER
);

INSERT INTO test VALUES (1, 'A', 4);
INSERT INTO test VALUES (1, 'A', 5);
INSERT INTO test VALUES (1, 'B', 8);
INSERT INTO test VALUES (2, 'C', 9);

SELECT ID, GROUP_CONCAT(NAME ORDER BY NAME ASC SEPARATOR ',')
FROM (
  SELECT ID, CONCAT(NAME, ':', GROUP_CONCAT(VALUE ORDER BY VALUE ASC SEPARATOR ',')) AS NAME
  FROM test
  GROUP BY ID, NAME
) AS A
GROUP BY ID;

SQL小提琴:http ://sqlfiddle.com/#!2/b5abe/9/0


2
是的,艾斯伯格+1。您的答案非常准确,而且更早。我在第一次回答时就犯了一个错误
Sami

9
SELECT ID, GROUP_CONCAT(CONCAT_WS(':', NAME, VALUE) SEPARATOR ',') AS Result 
FROM test GROUP BY ID

7
如果您可以在答案中添加一些说明,那就太好了。这是改善此问题和将来答案的建议。谢谢!
路易斯·克鲁兹

5

首先,我看不出拥有不唯一ID的原因,但我想它是连接到另一个表的ID。其次,不需要子查询,这会破坏服务器。您可以在一个查询中执行此操作,就像这样

SELECT id,GROUP_CONCAT(name, ':', value SEPARATOR "|") FROM sample GROUP BY id

您将获得快速正确的结果,并且可以将结果除以分隔符“ |”。我总是使用此分隔符,因为不可能在字符串中找到它,因此它是唯一的。拥有两个A毫无疑问,您只需识别值即可。或者,您可以再增加一个带字母的栏,效果更好。像这样 :

SELECT id,GROUP_CONCAT(DISTINCT(name)), GROUP_CONCAT(value SEPARATOR "|") FROM sample GROUP BY name

2
 SELECT id, GROUP_CONCAT(CONCAT_WS(':', Name, CAST(Value AS CHAR(7))) SEPARATOR ',') AS result 
    FROM test GROUP BY id

您必须使用强制转换或转换,否则将返回BLOB

结果是

id         Column
1          A:4,A:5,B:8
2          C:9

您必须通过python或java之类的程序再次处理结果


0

IF OBJECT_ID('master..test') is not null Drop table test

CREATE TABLE test (ID INTEGER, NAME VARCHAR (50), VALUE INTEGER );
INSERT INTO test VALUES (1, 'A', 4);
INSERT INTO test VALUES (1, 'A', 5);
INSERT INTO test VALUES (1, 'B', 8);
INSERT INTO test VALUES (2, 'C', 9);

select distinct NAME , LIST = Replace(Replace(Stuff((select ',', +Value from test where name = _a.name for xml path('')), 1,1,''),'<Value>', ''),'</Value>','') from test _a order by 1 desc

我的表名是test,为了简单起见,我使用了For XML Path('')语法。填充函数将一个字符串插入另一个字符串。它在开始位置删除第一个字符串中指定长度的字符,然后在开始位置将第二个字符串插入第一个字符串。

STUFF函数如下所示:STUFF(character_expression,start,length,character_expression)

character_expression是字符数据的表达式。character_expression可以是字符或二进制数据的常量,变量或列。

start是一个整数值,指定开始删除和插入的位置。如果start或length为负,则返回空字符串。如果开始时间比第一个character_expression长,则返回空字符串。start可以是bigint类型。

length是一个整数,指定要删除的字符数。如果length大于第一个character_expression,则删除会一直进行到最后一个character_expression中的最后一个字符。长度可以是bigint类型。


0

SELECT id,Group_concat(column)FROM(SELECT id,Concat(name,':',Group_concat(value))AS column from mytbl GROUP BY id,name)tbl GROUP BY id;

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.