2012-11-19 257 views
72

如果我有一个表在MySQL以下数据:如何使用GROUP_CONCAT在CONCAT在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,但我不知道它是如何工作的。

回答

100
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 Demo。确切地说你需要什么。

更新 分两步拆分。首先,我们得到一个表格,其中包含所有值(逗号分隔)与唯一的[名称,ID]。然后,从获得的表格中我们得到的所有名称和值作为对每一个唯一的ID 单个值见这说明如下SQL Fiddle Demo(向下滚动,因为它有两个结果集)

编辑有阅读问题上的错误,我仅通过id分组。但是,如果需要两个group_contacts(值按照Name和id分组,然后通过id分组)。 以前的答案是

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

你可以看到它实现这里:SQL Fiddle Demo

+0

这不会给Biswa要求什么。 – eisberg

+3

谢谢萨米这就是我要求的@biswa – Biswa

+2

我认为它很重要,警告人们只使用一种分离器可能是不利的。我建议将“名称”分隔符设置为分号(;),值分隔符可以保留为逗号(,) –

15

尝试:

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

是eisberg +1。你的回答非常准确和早。我在第一次回答时出错了 – Sami

+0

@Sami谢谢! – eisberg

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 

我的表名是测试,并为concatination我用的是对于XML路径( '' ) 句法。 stuff函数将字符串插入另一个字符串中。它删除起始位置第一个字符串中指定长度的字符 ,然后将第二个字符串插入到起始位置的第一个字符串 。

STUFF功能看起来像这样:STUFF(一个character_expression,启动,长度,一个character_expression)

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

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

长度 是一个整数,指定要删除的字符数。如果长度比第一个字符表达式长,则会发生 直到最后一个字符表达式中的最后一个字符。长度可以是bigint类型。

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

如果你可以给你的答案添加一些描述,那将是很好的。这是一个改进这个和未来答案的建议。谢谢! –

+0

upvoted for not using a subselect – Heinz

+0

谢谢你的回答。这对我有很大的帮助。 –

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

,你必须使用CAST或转换,否则将返回BLOB

结果是

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

您必须通过程序如Python或Java

处理再次引起
2

首先,我没有看到具有不唯一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