SQL Server en la práctica

Resultados fiables de STRING_AGG en SQL Server

Define orden, duplicados, valores ausentes y límites de longitud de tus listas y elige JSON cuando necesites conservar una estructura exacta.

Una lista separada por comas parece una tarea de presentación, pero depende de varias decisiones sobre los datos. ¿Qué filas forman cada grupo? ¿Los duplicados importan? ¿Debe mostrarse un espacio para lo desconocido? ¿Qué orden espera el usuario? STRING_AGG simplifica la concatenación sin resolver esas preguntas.

Los ejemplos requieren SQL Server 2017 o posterior. WITHIN GROUP para ordenar necesita compatibilidad de base de al menos 110. Comprueba ambas condiciones cuando el mismo código se comporta de forma diferente entre entornos.

Definir orden y valores ausentes

Los datos incluyen intencionadamente una etiqueta repetida y NULL.

DECLARE @Tags table (DocumentId int, TagId int, Tag nvarchar(100));
INSERT @Tags VALUES
(1, 1, N'Tuning'), (1, 2, N'Backup'), (1, 3, N'Tuning'),
(1, 4, NULL), (2, 5, N'Security');

SELECT DocumentId,
       STRING_AGG(CONVERT(nvarchar(max), Tag), N', ')
       WITHIN GROUP (ORDER BY Tag, TagId) AS TagList
FROM @Tags
GROUP BY DocumentId;

El documento 1 produce Backup, Tuning, Tuning con la comparación alfabética ilustrada. NULL no aporta texto ni un separador adicional. El documento 2 produce Security. STRING_AGG no elimina duplicados. Un ORDER BY exterior ordenaría los grupos devueltos, no los elementos interiores.

WITHIN GROUP define ese orden. TagId resuelve empates entre etiquetas iguales según la comparación. Si el negocio necesita orden de asignación, usa una secuencia real. La intercalación influye en comparación y posición de acentos y mayúsculas; prueba los valores que almacena la aplicación.

NULL no equivale a una cadena vacía. NULL se omite; la cadena vacía sigue siendo un valor y puede dejar un separador aparentemente inexplicable. Acuerda dónde normalizar entradas vacías o compuestas solo por espacios. No recortes códigos significativos únicamente para embellecer el resultado.

Para representar ausencias, sustituye NULL antes de agregar. El marcador no debería confundirse con un valor real. También puedes conservar un null auténtico mediante salida estructurada. Mostrar Desconocido no modifica la ausencia del dato original.

Quitar duplicados en la relación correcta

Si la lista debe contener etiquetas únicas, elimina las repeticiones antes de concatenar y en el nivel adecuado.

;WITH DistinctTags AS (
    SELECT DISTINCT DocumentId, Tag
    FROM @Tags
    WHERE Tag IS NOT NULL
)
SELECT DocumentId,
       STRING_AGG(CONVERT(nvarchar(max), Tag), N', ')
       WITHIN GROUP (ORDER BY Tag) AS TagList
FROM DistinctTags
GROUP BY DocumentId;

El documento 1 devuelve ahora Backup, Tuning. DISTINCT considera DocumentId y Tag conjuntamente, por lo que la misma etiqueta puede seguir apareciendo en otro documento. Una deduplicación global perdería esa relación.

Revisa las uniones antes de incorporar DISTINCT. Un documento con varios comentarios y varias etiquetas puede multiplicar las filas intermedias. Quitar repeticiones al final puede esconder la multiplicación mientras otras sumas siguen siendo incorrectas. Agrega primero la relación de etiquetas y después une su resultado de una fila por documento.

Las reglas de igualdad también importan. Una intercalación insensible a mayúsculas puede fusionar grafías distintas. Si necesitas una forma preferida para mostrar, establece una regla explícita. DISTINCT no decide por sí mismo qué variante debe ser canónica.

Controlar tamaño y contrato de salida

Convierte la expresión de entrada a nvarchar(max) antes de STRING_AGG si son legítimas listas largas. El tipo devuelto se deriva de la entrada. Convertir después de completar la agregación llega tarde para evitar su límite original. Mantén compatibles los tipos de valores y separador.

Permitir un tipo grande no significa que una respuesta ilimitada sea adecuada. Cientos de miles de relaciones pueden consumir memoria y crear una carga de red enorme. Define límites prácticos, devuelve elementos paginados o usa una exportación específica.

Una lista con comas no es un intercambio sin pérdida cuando los valores contienen comas, comillas o saltos de línea. FOR JSON conserva estructura y escape para una API. Tampoco sustituyas la relación normalizada si necesitas filtrar, validar o modificar etiquetas individualmente.

Prueba duplicados, NULL, valores vacíos, idiomas diferentes, separadores dentro del contenido y resultados superiores al límite habitual. Si parece truncado, compara la longitud real en la base con los límites de visualización del cliente antes de cambiar SQL. La agregación debe conservar el significado hasta el consumidor final.

Referencias técnicas: Microsoft Learn: STRING_AGG · Microsoft Learn: FOR JSON.

Pregunta sobre este artículo

¿Tiene alguna pregunta sobre este tema?

Cuéntenos qué está evaluando o dónde tiene dificultades. Le responderemos con una recomendación práctica.

Inquiries are not enabled in this preview.

Hacer una pregunta sobre este artículo