Convertir filas a cadenas en Teradata (II)

El viejo problema de convertir filas a cadenas de caracteres es un tema recurrente y ha sido tratado aquí. Normalmente hay que recurrir a algún tipo de recursividad (incluso en Oracle) y suele resultar un tanto engorroso.

Pero resulta que hay otro método. Aunque es un tanto extraño, ya que necesita utilizar Teradata XML Services, y más específicamente la función XMLAGG.

Esta función agrega múltiples filas para construir un valor XML (devuelve un XMLTYPE). Pero lo interesante es que podemos utilizarla para algo que no tiene que ver con XML: convertir filas en cadenas.

Veamos cómo:

 BTEQ -- Enter your SQL request or BTEQ command:
SELECT * FROM PRUEBA08;


 *** Query completed. 4 rows found. 2 columns returned.
 *** Total elapsed time was 1 second.

       ID_N  C_TXT
-----------  -------------------------
          3  TRES
          1  UNO
          4  CUATRO
          2  DOS


 BTEQ -- Enter your SQL request or BTEQ command:
SELECT XMLAGG(C_TXT ORDER BY ID_N) FROM CARLOS.PRUEBA08;


 *** Query completed. One row found. One column returned.
 *** Total elapsed time was 1 second.

XMLAGG(C_TXT ORDER BY ID_N ASC RETURNING SEQUENCE)
--------------------------------------------------
UNO DOS TRES CUATRO

¿Así de fácil? Casi. Hay que tener en cuenta que XMLAGG se comporta como una función de agregación (sí, como SUM(), COUNT(), MAX()…):

 BTEQ -- Enter your SQL request or BTEQ command:
SELECT ID_N,XMLAGG(C_TXT ORDER BY ID_N) FROM CARLOS.PRUEBA08;

 *** Failure 3504 Selected non-aggregate values must be part of the associated group.
                Statement# 1, Info =0
 *** Total elapsed time was 1 second.

Exacto:

 BTEQ -- Enter your SQL request or BTEQ command:
SELECT ID_N,XMLAGG(C_TXT ORDER BY ID_N) 
FROM CARLOS.PRUEBA08 GROUP BY 1;


 *** Query completed. 4 rows found. 2 columns returned.
 *** Total elapsed time was 1 second.

       ID_N XMLAGG(C_TXT ORDER BY ID_N ASC RETURNING SEQUENCE)
----------- --------------------------------------------------------------------------------
          3 TRES
          1 UNO
          4 CUATRO
          2 DOS

Teniendo eso claro, lo tenemos casi:

 BTEQ -- Enter your SQL request or BTEQ command:
INSERT INTO CARLOS.PRUEBA08 VALUES (1,'DOS');


 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.


 BTEQ -- Enter your SQL request or BTEQ command:


INSERT INTO CARLOS.PRUEBA08 VALUES (1,'TRES');


 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.


 BTEQ -- Enter your SQL request or BTEQ command:


INSERT INTO CARLOS.PRUEBA08 VALUES (2,'TRES');


 *** Insert completed. One row added.
 *** Total elapsed time was 1 second.
 
 BTEQ -- Enter your SQL request or BTEQ command:
SELECT * FROM CARLOS.PRUEBA08 ORDER BY 1;


 *** Query completed. 7 rows found. 2 columns returned.
 *** Total elapsed time was 1 second.

       ID_N  C_TXT
-----------  -------------------------
          1  UNO
          1  DOS
          1  TRES
          2  DOS
          2  TRES
          3  TRES
          4  CUATRO

Entonces:

  BTEQ -- Enter your SQL request or BTEQ command:
SELECT ID_N, XMLAGG(C_TXT) 
FROM CARLOS.PRUEBA08 GROUP BY 1 ORDER BY 1;


 *** Query completed. 4 rows found. 2 columns returned.
 *** Total elapsed time was 1 second.

       ID_N XMLAGG(C_TXT RETURNING SEQUENCE)
----------- ----------------------------------------------------------
          1 UNO DOS TRES
          2 DOS TRES
          3 TRES
          4 CUATRO

Sólo queda un asunto menor: XMLAGG devuelve XML:

 BTEQ -- Enter your SQL request or BTEQ command:
SELECT ID_N,
       TYPE(XMLAGG(C_TXT)) 
  FROM CARLOS.PRUEBA08 GROUP BY 1 ORDER BY 1;


 *** Query completed. 4 rows found. 2 columns returned.
 *** Total elapsed time was 1 second.

       ID_N  Type(XMLAGG(C_TXT ORDER BY ID_N ASC RETURNING SEQUENCE))
-----------  --------------------------------------------------------
          1  SYSUDTLIB.XML
          2  SYSUDTLIB.XML
          3  SYSUDTLIB.XML
          4  SYSUDTLIB.XML

Por lo que un ‘cast‘ le pone la guinda al pastel:

 BTEQ -- Enter your SQL request or BTEQ command:
SELECT ID_N, 
       XMLAGG(C_TXT) (VARCHAR(64)) 
  FROM CARLOS.PRUEBA08 GROUP BY 1 ORDER BY 1;


 *** Query completed. 4 rows found. 2 columns returned.
 *** Total elapsed time was 1 second.

       ID_N  XMLAGG(C_TXT RETURNING SEQUENCE)
-----------  ----------------------------------------------------------------
          1  UNO DOS TRES
          2  DOS TRES
          3  TRES
          4  CUATRO

Y si en vez de un espacio queremos un separador específico (‘|’, ‘;’, ‘,’…), es un juego de niños implementarlo.

Saludos.

Carlos.

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: