2011-08-25 34 views
10

Cómo obtener la función incorporada para los valores de columna separados por comas en sql en DB2, por ejemplo, si hay columnas con esta ID de política y tiene 3 filas con el mismo ID pero tienen tres roles diferentes en tres filas, entonces debería recuperar las filas en una fila "3,4,5"DB2 salida separada por comas

por ejemplo

1. 4555 "2" 
2. 4555 "3" 
3. 4555 "4" 

salida 4555 2,3,4 en un DB2 en una fila

Respuesta

3

Esto es exactamente lo que necesita:

http://radheshk.blogspot.com/2008/02/sql-tips-techniques-string-aggregation.html

Lamentablemente, no hay forma de definir una función de agregado personalizado en DB2 de forma sencilla (o no que yo sepa). Entonces uno debe recurrir a consultas recursivas, como en el ejemplo anterior.

Otra manera de resolver este problema está relacionado con los cursores, pero eso es probablemente lo que es peor ...

+0

Gracias por la respuesta – gaurav

-1

Prueba esto:

SELECT GROUP_CONCAT(field1, field2, field3 ,field4 SEPARATOR ', ') 
+0

lo hará ser campo1 aquí – gaurav

+0

Campo1: 1.4555 - SELECCIONE GROUP_CONCAT (campo1, campo3, campo4 SEPARATOR ',') –

+0

Ca n por favor, crea tu pregunta?: D –

7

Dependiendo de la versión de DB2 que tenga, puede utilizar las funciones XML para lograrlo.

tabla de ejemplo con algunos datos

create table myTable (id int, category int); 
insert into myTable values (1, 1); 
insert into myTable values (2, 2); 
insert into myTable values (3, 1); 
insert into myTable values (4, 2); 
insert into myTable values (5, 1); 

Los resultados agregados utilizando funciones XML

select category, 
    xmlserialize(XMLAGG(XMLELEMENT(NAME "x", id)) as varchar(1000)) as ids 
    from myTable 
    group by category; 

resultados:

CATEGORY IDS 
-------- ------------------------ 
     1 <x>1</x><x>3</x><x>5</x> 
     2 <x>2</x><x>4</x> 

utilizar remplace para que el resultado se vea mejor

select category, 
     replace(
     replace(
     replace(
      xmlserialize(XMLAGG(XMLELEMENT(NAME "x", id)) as varchar(1000)) 
      , '</x><x>', ',') 
      , '<x>', '') 
      , '</x>', '') as ids 
    from myTable 
    group by category; 

resultado limpiado

CATEGORY IDS 
-------- ----- 
     1 1,3,5 
     2 2,4 

acabamos de ver una mejor solución utilizando XMLTEXT en lugar de XmlElement here.

26

LISTAGG función es una función nueva en DB2 LUW 9.7

ver ejemplo:

create table myTable (id int, category int); 

insert into myTable values (1, 1); 
insert into myTable values (2, 2); 
insert into myTable values (5, 1); 
insert into myTable values (3, 1); 
insert into myTable values (4, 2); 

ejemplo: seleccionar sin ningún orden en la columna agrupado

select category, LISTAGG(id, ', ') as ids from myTable group by category; 

resultado:

CATEGORY IDS 
--------- ----- 
1   1, 5, 3 
2   2, 4 

ejemplo: seleccionar con el fin por la cláusula en la columna agrupado

select 
    category, 
    LISTAGG(id, ', ') WITHIN GROUP(ORDER BY id ASC) as ids 
from myTable 
group by category; 

resultado:

CATEGORY IDS 
--------- ----- 
1   1, 3, 5 
2   2, 4 
7

Creo que con esta consulta más pequeño, puede hacer lo que quiera. Esto es equivalente a GROUP_CONCAT de MySQL en DB2.

SELECT 
NUM, 
SUBSTR(xmlserialize(xmlagg(xmltext(CONCAT(', ',ROLES))) as VARCHAR(1024)), 3) as ROLES 
FROM mytable 
GROUP BY NUM; 

Esto sería algo así como:

NUM ROLES 
---- ------------- 
1  111, 333, 555 
2  222, 444 

assumming su resultado original fue algo así:

NUM ROLES 
---- --------- 
1  111 
2  222 
1  333 
2  444 
1  555 
0

Mi problema era transponer los campos de fila (CLOB) a la columna (VARCHAR) con un CSV y usa la tabla transpuesta para informar. Debido a que la transposición en la capa de informe ralentiza el informe.

Una forma de hacerlo es utilizar SQL recursivo. Puede encontrar muchos artículos al respecto, pero es difícil y consume muchos recursos si quiere unir todas sus columnas recursivas transpuestas.

Creé varias tablas temporales globales donde almacené columnas transpuestas individuales con un identificador de clave. Finalmente, tuve 6 tablas temporales para unir 6 columnas, pero debido a la asignación limitada de recursos no pude juntar todas las columnas. Opté por debajo de 3 fórmulas y luego tuve que ejecutar 1 consulta que me dio salida en 10 segundos.

Encontré varios artículos sobre el uso de funciones XML2CLOB y encontré 3 formas diferentes.

REPLACE(VARCHAR(XML2CLOB(XMLAGG(XMLELEMENT(NAME "A",ALIASNAME.ATTRIBUTENAME)))),'', ',') AS TRANSPOSED_OUTPUT 
NVL(TRIM(',' FROM REPLACE(REPLACE(REPLACE(CAST(XML2CLOB(XMLAGG(XMLELEMENT(NAME "E", ALIASNAME.ATTRIBUTENAME))) AS VARCHAR(100)),'',' '),'',','), '', 'Nothing')), 'Nothing') as TRANSPOSED_OUTPUT 
 
RTRIM(REPLACE(REPLACE(REPLACE(VARCHAR(XMLSERIALIZE(XMLAGG(XMLELEMENT(NAME "A",ALIASNAME.ATTRIBUTENAME) ORDER BY ALIASNAME.ATTRIBUTENAME) AS CLOB)), '',','),'',''),'','')) AS TRANSPOSED_OUTPUT 

Asegúrese de que está lanzando su "attributeName" a varchar en una subconsulta y luego llamar aquí.

0

otra posibilidad, la CTE recursiva

with tablewithrank as (
    select id, category, rownumber() over(partition by category order by id) as rangid , (select count(*) from myTable f2 where f1.category=f2.category) nbidbycategory 
    from myTable f1 
    ), 
    cte (id, category, rangid, nbidbycategory, rangconcat) as (
    select id, category, rangid, nbidbycategory, cast(id as varchar(500)) from tablewithrank where rangid=1 
    union all 
    select f2.id, f2.category, f2.rangid, f2.nbidbycategory, cast(f1.rangconcat as varchar(500)) || ',' || cast(f2.id as varchar(500)) from cte f1 inner join tablewithrank f2 on f1.rangid=f2.rangid -1 and f1.category=f2.category 
    ) 
    select category, rangconcat as IDS from cte 
    where rangid=nbidbycategory 
Cuestiones relacionadas