En un posteo reciente use un “patrón” de comando de SQL que tiene la siguiente forma:
SET @Comando=”
SELECT TOP 10 @Comando=@Comando+CHAR(13)+CHAR(10)+Indice
FROM dbo.FragmentacionIndices
ORDER BY TotalPages DESC;
Este comando permite concatenar un texto usando una variable, pero mi amigo Eladio Rincón, que el equipo de desarrollo de SQL, sostiene que ese comando no está garantizado que brinda resultados consistentes.
Ahora para otro proyecto tengo que concatenar una de nombres que están relacionados con una tabla. Despues de estudiar algunas alternativas me gusta la siguiente solución:
; WITH ProveedoresOrdenados (ProductID, VendorId, NumProveedor) AS
(
SELECT ProductVendor.ProductID
, ProductVendor.VendorID
, ROW_NUMBER() OVER ( PARTITION BY ProductID ORDER BY VendorID) AS NumProveedor
FROM Purchasing.ProductVendor
)
, ProdVendedorRecursivo (ProductId, VendorId, Description, NumProveedor)
AS (
SELECT ProveedoresOrdenados.ProductID
, ProveedoresOrdenados.VendorId
, CAST(ProveedoresOrdenados.VendorID AS VARCHAR(8000))
, ProveedoresOrdenados.NumProveedor
FROM ProveedoresOrdenados
WHERE NumProveedor=1
UNION ALL
SELECT ProveedoresOrdenados.ProductId, ProveedoresOrdenados.VendorId
, ProdVendedorRecursivo.Description + ‘, ‘ + CAST(ProveedoresOrdenados.VendorId AS VARCHAR(8000))
, ProveedoresOrdenados.NumProveedor
FROM ProveedoresOrdenados
JOIN ProdVendedorRecursivo
ON ProveedoresOrdenados.ProductID=ProdVendedorRecursivo.ProductId
AND ProveedoresOrdenados.NumProveedor=ProdVendedorRecursivo.NumProveedor+1
)
SELECT ProdVendedorRecursivo.ProductId, ProdVendedorRecursivo.Description
FROM ProdVendedorRecursivo
JOIN (SELECT ProductId, MAX(ProdVendedorRecursivo.NumProveedor) AS NumProveedor
FROM ProdVendedorRecursivo GROUP BY ProductId) AS Last
ON ProdVendedorRecursivo.ProductId=Last.ProductId
AND ProdVendedorRecursivo.NumProveedor=Last.NumProveedor
El ejemplo se basa en la BD de AdventureWorks y la tabla ProductVendors. ProductVendors es captura una relación de muchos a muchos entre Products y Vendors el comando pretende obtener para cada producto una columna con la lista de Proveedores (Vendors).
El comando usa 2 CTEs y algunas funciones disponibles desde SQL 2005 para obtener el resultado deseado. La primera consulta usa ROW_NUMBER para obtener un número consecutivo de proveedor para cada producto, este número facilita los JOINS de la segunda consulta. La segunda consulta aprovecha las consultas recursivas para concatenar la descripción, de manera tal que cada línea tiene la descripción de todos los anteriores. Finalmente la consulta filtra y despliega solo la última fila de cada producto.
No estoy seguro de su desempeño en tablas de tamaño considerable.