Concat SQL中的所有列值

如何将来自sql查询返回的不同行的所有列值连接成一个值? 这是一个例子:

一个查询返回:

 FOO
 ------
 RES1

 RES2

 RES3

现在我想要得到如下结果:

 FOOCONCAT
 -----
 RES1RES2RES3

有没有办法在SQL中做到这一点?

SQL Server

 SELECT col1 AS [text()] FROM foo FOR XML PATH ('') 

MySQL

 SELECT GROUP_CONCAT(col1 SEPARATOR '') FROM foo 

PostgreSQL

 SELECT array_to_string ( ARRAY ( SELECT col1 FROM foo ), '' ) 

Oracle

 SELECT * FROM ( SELECT col1, ROW_NUMBER() OVER(ORDER BY 1) AS rn FROM foo MODEL DIMENSION BY (rn) MEASURES (col1, col1 AS group_concat, 0 AS mark) RULES UPDATE ( group_concat[rn > 1] = group_concat[CV() - 1] || col1[CV()], mark[ANY] = PRESENTV(mark[CV() + 1], 0, 1) ) ) WHERE mark = 1 

Quassnoi的Oracle解决scheme相当出色,但我发现使用SYS_CONNECT_BY_PATH()而不是MODEL魔术更简单 。

 SELECT REPLACE(MAX(SYS_CONNECT_BY_PATH(foo, '/')), '/', '') conc FROM ( SELECT T_FOO.*, ROW_NUMBER() OVER (ORDER BY FOO) R FROM T_FOO ) START WITH r=1 CONNECT BY PRIOR r = r-1; 

假设它是一列有多个值,这种方法适用于MS SQL Server(我不能说其他系统)。

 declare @result varchar(max) set @result = '' select @result = @result + RES from (query goes here) 

mysql的方式:

 select group_concat(somecolumn separator '') from sometable 

这是你正在寻找的答案。 我有一种感觉,解决scheme在CONNECT BY操作中,我刚才没有使用过SYS_CONNECT_BY_PATH伪列(显示树中节点的完整path,用“/”分隔节点名称)。 假设你之前的一组“foo”值是表中的多行,按列“myKey”分组,例如:

 myKey foo -------- ---------- group 1 apple group 1 orange group 1 pear group 2 ape group 2 bear group 2 kitten 

您可以将数据视为树模式,并假设每个组的值代表分支上的节点。 在这种情况下,你会这样做:

  SELECT myKey , SUBSTR(MAX(REPLACE(SYS_CONNECT_BY_PATH(foo, '/') ,'/' ,' ' ) ) ,2 ) FooConcat FROM ( SELECT MyKey , Foo , row_number() OVER (Partition by myKey order by myKey) NodeDepth FROM MyTable ) START WITH NodeDepth = 1 CONNECT BY PRIOR myKey = myKey AND PRIOR NodeDepth = NodeDepth -1 GROUP BY myKey ; 

当然,连接值的顺序是随机的, 如果你的表有另一个列(“栏”),你可以使用作为一个上升和连续的sorting字段,你可以免去子查询(只存在一个虚拟的深度树),并直接使用表,用barreplaceNodeDepth。

编辑:自8.4.0版本以来,CUBRID提供了90%与MySQL的兼容性 。 因此,它支持与MySQL中语法相似的GROUP_CONCAT :

 CREATE TABLE t(i int); INSERT INTO t VALUES (4),(2),(3),(6),(1),(5); SELECT GROUP_CONCAT(i*2+1 ORDER BY 1 SEPARATOR '') FROM t; group_concat(i*2+1 order by 1 separator '') ====================== '35791113' 

相当强大,不是吗? 以下是CUBRID本地支持的替代解决scheme 。

 SELECT MAX(SYS_CONNECT_BY_PATH(s_name, '')) AS conc_s_name FROM ( SELECT ROWNUM AS r, s_name FROM code ) AS res START WITH r = 1 CONNECT BY PRIOR r = r - 1; 

非常有趣的是,这种连接CUBRID中的不同行列值的方式几乎和Oracle提供的@devio一样。 在CUBRID中,它看起来更容易一些。

 select cast(res1 as varchar)+cast(res2 as varchar)+cast(res3 as varchar) as fooconcat from foo 

如果列已经是string,则不需要投射,只需执行以下操作:

 select res1 + res2 + res3 as fooconcat from foo 

对于来自多行的数据,请使用PIVOT 。

连接string取决于你正在使用的数据库(你havnt提到你的问题,所以在这里去了什么版本)…

在Oracle和DB2中,您可以使用CONCAT函数… CONCAT(string, string)

SQL Server中可以使用'+'运算符… string1 + string2 + string3

在MySQL中,它是CONCAT(string, string... n_string)

最后在PostgreSQL中是TEXTCAT(string, string)

…我从这个有点酷的书中得到了这个,我已经坐在O'Reilly的桌面SQL Pocket Guide上了…看看吧!

🙂

这可能不是你要找的东西,但是我过去的运气好像是这样的:

 SELECT MAX(DECODE(fookey, 1, foo, NULL)) || MAX(DECODE(fookey, 2, foo, NULL)) || MAX(DECODE(fookey, 3, foo, NULL)) || MAX(DECODE(fookey, 4, foo, NULL)) , groupingvalue FROM mytable GROUP BY groupingvalue; 

它是独立于平台的,当你有一个任意的,但有限的foo值时,它运行的很好,而且它们是基于其他一些关键值的。 例如,如果您有一张发票表,并且您希望从单行上的发票中看到所有行时间,并且有5个行项目的上限,则它将如下所示:

 SELECT MAX(DECODE(lineno, 1, foo, NULL)) || ', ' || MAX(DECODE(lineno, 2, foo, NULL)) || ', ' || MAX(DECODE(lineno, 3, foo, NULL)) || ', ' || MAX(DECODE(lineno, 4, foo, NULL)) || ', ' || MAX(DECODE(lineno, 5, foo, NULL)) , invoiceid FROM lineitem GROUP BY invoiceid; 

SQL Server 2008 R2:

 declare @ColumnNameList VARCHAR(MAX) SELECT @ColumnNameList = COALESCE(@ColumnNameList +',' ,'') + ColumnName FROM <<table name>> select @ColumnNameList 

从[Table]中select([col1] +','+ [col2] +','+ [col3] +','+ [col4])作为[MyCol]