varios - unir varias filas en una sola sql




Consulta SQL para concatenar valores de columna de varias filas en Oracle (9)

¿Sería posible construir SQL para concatenar valores de columna de múltiples filas?

Lo siguiente es un ejemplo:

Tabla A

PID
A
B
C

Tabla B

PID   SEQ    Desc

A     1      Have
A     2      a nice
A     3      day.
B     1      Nice Work.
C     1      Yes
C     2      we can 
C     3      do 
C     4      this work!

La salida del SQL debería ser -

PID   Desc
A     Have a nice day.
B     Nice Work.
C     Yes we can do this work!

Entonces, básicamente, ¿la columna Desc para la tabla de salida es una concatenación de los valores de SEQ de la Tabla B?

Cualquier ayuda con el SQL?


  1. LISTAGG ofrece el mejor rendimiento si la clasificación es obligatoria (00: 00: 05.85)

    SELECT pid, LISTAGG(Desc, ' ') WITHIN GROUP (ORDER BY seq) AS description FROM B GROUP BY pid;

  2. COLLECT ofrece el mejor rendimiento si la clasificación no es necesaria (00: 00: 02.90):

    SELECT pid, TO_STRING(CAST(COLLECT(Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;

  3. COLLECT con el pedido es un poco más lento (00: 00: 07.08):

    SELECT pid, TO_STRING(CAST(COLLECT(Desc ORDER BY Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;

Todas las demás técnicas fueron más lentas.


Antes de ejecutar una consulta de selección, ejecute esto:

SET SERVEROUT ON SIZE 6000

SELECT XMLAGG(XMLELEMENT(E,SUPLR_SUPLR_ID||',')).EXTRACT('//text()') "SUPPLIER" 
FROM SUPPLIERS;

Con la cláusula modelo de SQL:

SQL> select pid
  2       , ltrim(sentence) sentence
  3    from ( select pid
  4                , seq
  5                , sentence
  6             from b
  7            model
  8                  partition by (pid)
  9                  dimension by (seq)
 10                  measures (descr,cast(null as varchar2(100)) as sentence)
 11                  ( sentence[any] order by seq desc
 12                    = descr[cv()] || ' ' || sentence[cv()+1]
 13                  )
 14         )
 15   where seq = 1
 16  /

P SENTENCE
- ---------------------------------------------------------------------------
A Have a nice day
B Nice Work.
C Yes we can do this work!

3 rows selected.

Escribí sobre esto here . Y si sigue el enlace al hilo OTN, encontrará algunos más, incluida una comparación de rendimiento.


En la selección donde desea su concatenación, llame a una función SQL.

Por ejemplo:

select PID, dbo.MyConcat(PID)
   from TableA;

Luego, para la función SQL:

Function MyConcat(@PID varchar(10))
returns varchar(1000)
as
begin

declare @x varchar(1000);

select @x = isnull(@x +',', @x, @x +',') + Desc
  from TableB
    where PID = @PID;

return @x;

end

La sintaxis del encabezado de función puede ser incorrecta, pero el principio funciona.



O la función Oracle STRAGG (columna).

Tengo que decir que este tipo de procesamiento es muy limitado ... si excedes el ancho del campo o ancho de la pantalla ...


Prueba este código:

 SELECT XMLAGG(XMLELEMENT(E,fieldname||',')).EXTRACT('//text()') "FieldNames"
    FROM FIELD_MASTER
    WHERE FIELD_ID > 10 AND FIELD_AREA != 'NEBRASKA';

También hay una función XMLAGG , que funciona en versiones anteriores a la 11.2. Debido a que WM_CONCAT no está documentado y no es compatible con Oracle , se recomienda no utilizarlo en el sistema de producción.

Con XMLAGG puede hacer lo siguiente:

SELECT XMLAGG(XMLELEMENT(E,ename||',')).EXTRACT('//text()') "Result" 
FROM employee_names

Lo que esto hace es

  • poner los valores de la columna ename (concatenada con una coma) de la tabla employee_names en un elemento xml (con la etiqueta E)
  • extraer el texto de esto
  • agregar el xml (concatenarlo)
  • llamar a la columna resultante "Resultado"

Hay algunas formas dependiendo de la versión que tenga: consulte la documentación de Oracle sobre técnicas de agregación de cadenas . Una muy común es usar LISTAGG :

SELECT pid, LISTAGG(Desc, ' ') WITHIN GROUP (ORDER BY seq) AS description
FROM B GROUP BY pid;

Luego únete a A para elegir los pids que quieras.

Nota: Fuera de la caja, LISTAGG solo funciona correctamente con columnas VARCHAR2 .







string-aggregation