Concatenar datos de una columna en una fila
- 3 minutos de lecturaMe he topado en varias ocasiones con la necesidad de crear una vista en la que un campo contiene concatenados el valor de varios registros de otra tabla. Casi siempre he acabado recurriendo a Google para recordar c贸mo hacerlo, porque, por alguna raz贸n que desconozco, esta informaci贸n no queda registrada en mi hipocampo.
En este art铆culo vamos a ver c贸mo conseguirlo con un ejemplo muy sencillo. Partimos de 3 tablas: autor, libro y libro_autor, que contienen, como podemos suponer, una relaci贸n de autores, libros y libro-autor. La estructura de estas tres tablas es la que se muestra en el siguiente diagrama.
Ahora supongamos que queremos mostrar el listado de todos los libros y que en una columna queremos que aparezcan concatenados el nombre de todos los autores del libro. El resultado que queremos obtener es el siguiente:
| id_libro | titulo | autores |
|---|---|---|
| 1 | libro1 | autor1, autor2 |
| 2 | libro2 | autor2, autor1 |
| 3 | libro3 | autor3 |
La forma m谩s sencilla de obtener este resultado es creando una funci贸n que devuelva el nombre de todos los autores, pasando como par谩metro el identificador del libro. Esto lo podemos hacer f谩cilmente haciendo uso de las funciones ISNULL o COALESCE. En este ejemplo, lo conseguimos mediante la funci贸n COALESCE.
CREATE FUNCTION dbo.DevuelveActores ( @id\_libro int )
RETURNS VARCHAR(40)
AS
BEGIN
DECLARE @autores VARCHAR(40)
SELECT @autores = COALESCE(@autores + ', ' + nombre, nombre)
FROM libro\_autor la
LEFT JOIN autor a ON la.id\_autor = a.id\_autor
WHERE id\_libro=@id\_libro
RETURN @autores
END
Ahora podemos, mediante la siguiente consulta, obtener el resultado deseado:
SELECT id_libro, titulo, autores = dbo.DevuelveActores(id_libro)
FROM libro
Otra opci贸n es hacer uso del modo PATH de la cl谩usula FOR XML. Este modo permite definir, mediante los nombres o alias de la columnas, la manera c贸mo se asignan los valores en el XML, as铆 como el nombre del elemento, pudiendo sobrescribir el valor _
SELECT nombre as \[data()\] FROM autor FOR XML PATH ('')
Haciendo uso de esta caracter铆stica, es posible montar una consulta con una subconsulta que devuelva todos los autores de un libro y reemplazar el espacio entre autores por el separador que queramos. Con la siguiente consulta obtenemos exactamente el mismo resultado que hemos conseguido antes con la funci贸n.
SELECT id_libro, titulo, autores = CAST( REPLACE( (
SELECT nombre as [data()]
FROM libro_autor la
LEFT JOIN autor a ON la.id_autor = a.id_autor
WHERE id_libro = l.id_libro
FOR XML PATH ('')
), ' ', ', ') AS NVARCHAR(40) )
FROM libro l
Dejo un enlace para descargar el script que contiene las consultas de los dos m茅todos explicados y la creaci贸n de todos los elementos de base de datos (tablas y funciones) que he utilizado en este ejemplo.