domingo, 12 de mayo de 2013

Concatenar varios registros en una sola columna

Supongamos que, en SQL Server, tenemos una tabla de proveedores y una tabla aparte donde se almacenan los números de teléfonos de dichos proveedores como registros separados. De modo que tendríamos algo similar a lo siguiente:

Proveedor:

codProveedor desRazonSocial ...
1 Proveedor de Prueba 1 ...
2 Proveedor de Prueba 2 ..

ProveedorTelefono:
codProveedor desTelefono
1 88881685
1 89000000
1 98012012
2 78912000
2 12345678

Supongamos que una de las necesidades de nuestro cliente es que mostremos, en un grid o tabla, cada proveedor con todos sus teléfonos en una sola columna separados por comas.

Como para con casi todo en la vida, hay varias formas de hacerlo; podríamos traernos todo en dos consultas separadas (o en una sola por medio de joins, con la información de los proveedores repetida) y ya en nuestra aplicación, por medio de un bucle, concatenar los teléfonos en un solo campo, o usar un store procedure con un cursor y hacer mas o menos lo mismo que en el punto anterior pero en el motor de base de datos o tantas otras aproximaciones.

También se puede utilizar la combinación de una función y una consulta de la siguiente manera:

Primero creamos una función para devolver los teléfonos concatenados por proveedor:
CREATE FUNCTION [dbo].[fnTelefonosProveedor] (@codProveedor int)
RETURNS varchar(600)
AS
BEGIN 
 DECLARE @listaTelefonos varchar(600)
 SET @listaTelefonos = null
 
 SELECT  @listaTelefonos = COALESCE(@listaTelefonos, '') +
  CASE
   WHEN @listaTelefonos IS NULL THEN ''
  ELSE
   ', '
  END
  + T.desTelefono
 FROM ProveedorTelefono T
 WHERE T.codProveedor = @codProveedor

 RETURN @listaTelefonos 
END
Esta función que recibe por parámetro el código del proveedor y retorna los teléfonos concatenados en campo varchar de hasta 600 caracteres. La combinación de la sentencia SELECT con el COALESCCE [si el primer parámetro es nulo devuelve el segundo parámetro] hace la magia de concatenar los teléfonos en una sola variable (@listaTelefonos) separados por coma.

Finalmente utilizamos nuestra función dentro de nuestra consulta:
SELECT P.conCodigoProveedor, P.nomRazonSocial, dbo.fnTelefonosProveedor(P.codProveedor) AS desTelefonos  FROM Proveedor P
Obteniendo algo similar a

codProveedor desRazonSocial desTelefonos
1 Proveedor de Prueba 1 88881685, 89000000, 98012012
2 Proveedor de Prueba 2 78912000, 12345678

Y ya con esto concatenamos varios registros en una sola columna...y es fácil de traducir a otros motores de base de datos.

0 comentarios: