string_agg - Concat todos los valores de columna en sql
stuff sql server (12)
¿Cómo concat todos los valores de columna de las filas diferenciadas devueltas de una consulta de SQL en un valor? Esto es un ejemplo:
una consulta devuelve:
FOO ------ RES1 RES2 RES3
Ahora quiero tener un resultado como el siguiente:
FOOCONCAT ----- RES1RES2RES3
¿Hay alguna manera de hacer esto en SQL?
Aquí está la respuesta que estás buscando; Tenía la sensación de que la solución estaba en la operación CONECTAR POR, simplemente no había usado la pseudocolumna SYS_CONNECT_BY_PATH anteriormente (que muestra la ruta completa al nodo en un árbol, separando los nombres de los nodos por una "/"). Suponiendo que su conjunto de valores "foo" antes son varias filas en una tabla, agrupadas por una columna "myKey", por ejemplo:
myKey foo
-------- ----------
group 1 apple
group 1 orange
group 1 pear
group 2 ape
group 2 bear
group 2 kitten
puede tratar los datos como si fueran un esquema de árbol y pretender que los valores de cada grupo representan nodos que bajan por una rama. En ese caso, harías esto:
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
;
Por supuesto, el orden de los valores concatenados sería aleatorio; Si su tabla tuviera otra columna ("barra") que pudiera usar como campo de ordenamiento ascendente y contiguo, podría prescindir de la subconsulta (que solo existe para colocar una profundidad imaginaria en el árbol) y usar la tabla directamente. Sustituyendo NodeDepth con barra.
Encontré la respuesta en ¿Cómo concatenar todos los registros en una columna devuelta por una consulta en una cadena varchar en T-SQL?
declare @s varchar(8000)
select @s = coalesce(@s + col, col) from tbl
Esto debería resolver
La concatenación de cadenas depende de la base de datos que está utilizando (no ha mencionado qué versión de su pregunta, así que aquí va) ...
En Oracle y DB2 puede usar la función CONCAT(string, string)
... CONCAT(string, string)
SQL Server puede usar el operador ''+'' ... string1 + string2 + string3
En MySQL es CONCAT(string, string... n_string)
Finalmente en PostgreSQL es TEXTCAT(string, string)
...
... Lo saqué de este pequeño y genial libro que tengo sentado en mi escritorio SQL Pocket Guide de O''Reilly ... ¡échale un vistazo!
:)
La forma mysql:
select group_concat(somecolumn separator '''') from sometable
La solución de Oracle de Quassnoi es bastante impresionante, pero found soluciones simpler utilizando SYS_CONNECT_BY_PATH () en lugar de la magia 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;
Puede que no sea lo que estás buscando, pero he tenido buena suerte en el pasado con construcciones como esta:
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;
Es independiente de la plataforma, y funciona bien cuando tiene un número arbitrario, pero limitado de valores para foo, y se basan en algún otro valor clave. Por ejemplo, si tiene una tabla de facturas y desea ver todos los tiempos de línea de la factura en una sola fila, concatenada, y tiene un límite superior de 5 artículos de línea, se vería así:
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
Seleccione ([col1] + '','' + [col2] + '','' + [col3] + '','' + [col4]) como [MiCol] De [Tabla]
Suponiendo que es una columna con varios valores, este enfoque funciona para MS SQL Server (no puedo hablar por otros sistemas).
declare @result varchar(max)
set @result = ''''
select @result = @result + RES
from (query goes here)
Edición: desde la versión 8.4.0, CUBRID proporciona un 90% de compatibilidad con MySQL. Por lo tanto, admite GROUP_CONCAT que tiene una sintaxis similar a la de MySQL:
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''
Bastante poderoso, ¿no es así? Y a continuación se muestra una solución alternativa soportada de forma nativa en CUBRID.
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;
Es tan interesante que esta forma de concatenar diferentes valores de columna de fila en CUBRID es casi idéntica a la forma de Oracle proporcionada por @devio. Sin embargo, en CUBRID parece un poco más fácil.
En SQL Server
:
SELECT col1 AS [text()]
FROM foo
FOR XML PATH ('''')
En MySQL
:
SELECT GROUP_CONCAT(col1 SEPARATOR '''')
FROM foo
En PostgreSQL
:
SELECT array_to_string
(
ARRAY
(
SELECT col1
FROM foo
), ''''
)
En 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
select cast(res1 as varchar)+cast(res2 as varchar)+cast(res3 as varchar) as fooconcat from foo
Si las columnas ya son cadenas, no necesita la conversión, solo puede hacer:
select res1 + res2 + res3 as fooconcat from foo
Para datos de varias filas, utilice PIVOT .