Tabla es:
+----+------+
| Id | Name |
+----+------+
| 1 | aaa |
| 1 | bbb |
| 1 | ccc |
| 1 | ddd |
| 1 | eee |
+----+------+
Salida requerida:
+----+---------------------+
| Id | abc |
+----+---------------------+
| 1 | aaa,bbb,ccc,ddd,eee |
+----+---------------------+
Consulta:
SELECT ID,
abc = STUFF(
(SELECT ',' + name FROM temp1 FOR XML PATH ('')), 1, 1, ''
)
FROM temp1 GROUP BY id
Esta consulta está funcionando correctamente. Pero solo necesito la explicación de cómo funciona o si hay alguna otra forma de hacerlo.
Me estoy confundiendo mucho al entender esto.
sql
sql-server
database
Puneet Chawla
fuente
fuente
ID
es único en una tabla diferente de diferentes entidades, y esta tabla está almacenando cosas que les pertenecen.Respuestas:
Así es como funciona:
1. Obtenga una cadena de elementos XML con FOR XML
Agregar FOR XML PATH al final de una consulta le permite generar los resultados de la consulta como elementos XML, con el nombre del elemento contenido en el argumento PATH. Por ejemplo, si tuviéramos que ejecutar la siguiente declaración:
Al pasar una cadena en blanco (FOR XML PATH ('')), obtenemos lo siguiente:
2. Elimine la coma inicial con COSAS
La instrucción STUFF literalmente "mete" una cadena en otra, reemplazando los caracteres dentro de la primera cadena. Sin embargo, la estamos usando simplemente para eliminar el primer carácter de la lista de valores resultante.
Los parámetros de
STUFF
son:Entonces terminamos con:
3. Únete a la identificación para obtener la lista completa
A continuación, solo unimos esto en la lista de ID en la tabla temporal, para obtener una lista de ID con nombre:
Y tenemos nuestro resultado:
¡Espero que esto ayude!
fuente
LISTAGG
función en Oracle 11gR2. Echo de menos esa funcionalidad en los días en que tengo que usar esto en su lugar. techonthenet.com/oracle/functions/listagg.phplist
función durante décadas. Desafortunadamente, Microsoft basó SQLServer en el ASE de Sybase, y nunca se molestó con una función de lista hasta el año pasado. Estoy de acuerdo, es alucinante. Y luego lo hacen, lo llamanstring_agg
. Pensé quelist
era bastante obvio.Este artículo cubre varias formas de concatenar cadenas en SQL, incluida una versión mejorada de su código que no codifica en XML los valores concatenados.
Para comprender lo que sucede, comience con la consulta interna:
Como está especificando
FOR XML
, obtendrá una única fila que contiene un fragmento XML que representa todas las filas.Como no ha especificado un alias de columna para la primera columna, cada fila se ajustará en un elemento XML con el nombre especificado entre paréntesis después de
FOR XML PATH
. Por ejemplo, si lo hubiera hechoFOR XML PATH ('X')
, obtendría un documento XML similar al siguiente:Pero, como no ha especificado un nombre de elemento, solo obtiene una lista de valores:
El
.value('.', 'varchar(max)')
simplemente recupera el valor del fragmento de XML resultante, sin XML que codifica todos los caracteres "especiales". Ahora tiene una cadena que se parece a:La
STUFF
función luego elimina la coma inicial, lo que le da un resultado final que se parece a:A primera vista, parece bastante confuso, pero tiende a funcionar bastante bien en comparación con algunas de las otras opciones.
fuente
TYPE
directiva le dice a SQL que devuelva los datos usando elxml
tipo. Sin ella, los datos se devuelven como unnvarchar(max)
. Se usa aquí para evitar problemas de codificación XML si hay caracteres especiales en laname
columna.TYPE
y.value('.', 'varchar(max)')
, puede terminar con entidades codificadas en XML en el resultado.El modo PATH se usa para generar XML a partir de una consulta SELECT
La salida es XML centrado en elementos donde cada valor de columna en el conjunto de filas resultante se ajusta en un elemento de fila. Como la cláusula SELECT no especifica ningún alias para los nombres de columna, los nombres de elementos secundarios generados son los mismos que los nombres de columna correspondientes en la cláusula SELECT.
Para cada fila del conjunto de filas se agrega una etiqueta.
Para el Paso 2: si especifica una cadena de longitud cero, el elemento de ajuste no se produce.
En el Paso 4 estamos concatenando los valores.
En el Paso 6 estamos agrupando la fecha por ID.
STUFF (source_string, start, length, add_string) Parámetros o argumentos source_string La cadena de origen a modificar. start La posición en source_string para eliminar caracteres de longitud y luego insertar add_string. longitud El número de caracteres para eliminar de source_string. add_string La secuencia de caracteres para insertar en source_string en la posición inicial.
fuente
','
columna especificada como, combinada con la('')
ruta xml posterior, hace que ocurra la concatenaciónSELECT 'a' FROM some_table FOR XML PATH('')
producirá:'aaaaaaa'
. Pero si el nombre de la columna se especificará:SELECT 'a' AS Col FROM some_table FOR XML PATH('')
se obtiene resultado:<Col>a</Col><Col>a</Col><Col>a</Col>
Hay una funcionalidad muy nueva en Azure SQL Database y SQL Server (a partir de 2017) para manejar este escenario exacto. Creo que esto serviría como un método oficial nativo para lo que está tratando de lograr con el método XML / STUFF. Ejemplo:
STRING_AGG - https://msdn.microsoft.com/en-us/library/mt790580.aspx
EDITAR: Cuando publiqué esto originalmente, mencioné SQL Server 2016, ya que pensé que lo vi en una característica potencial que se incluiría. O lo recordaba incorrectamente o algo cambió, gracias por la edición sugerida que corrige la versión. Además, estoy bastante impresionado y no estaba completamente consciente del proceso de revisión de varios pasos que me llevó a una opción final.
fuente
En
for xml path
, si definimos cualquier valor como[ for xml path('ENVLOPE') ]
entonces, estas etiquetas se agregarán con cada fila:fuente
Aquí, en la consulta anterior, la función STUFF se usa para eliminar la primera coma
(,)
de la cadena xml generada y(,aaa,bbb,ccc,ddd,eee)
luego se convertirá(aaa,bbb,ccc,ddd,eee)
.Y
FOR XML PATH('')
simplemente convierte los datos de la columna en una(,aaa,bbb,ccc,ddd,eee)
cadena, pero en PATH estamos pasando '', por lo que no creará una etiqueta XML.Y al final hemos agrupado los registros usando la columna ID .
fuente
Hice la depuración y finalmente devolví mi consulta 'rellena' de la manera normal.
Simplemente
me da contenido de la tabla para escribir en una tabla de registro desde un desencadenador que depuro.
fuente
fuente
MATERIAL ((SELECCIONE distinto ',' + CAST (T.ID) DE la Tabla T donde T.ID = 1 PARA RUTA XML ('')), 1,1, '') COMO Nombre
fuente
Estoy usando frecuentemente con la cláusula where
fuente