Estoy trabajando en una consulta SQL usando pvots con columnas dinámicas en SQL Server (T-sql). En lugar de enviar mi larga consulta, estoy ilustrando mi problema con un modelo simplificado.Pivotes con columnas dinámicas en SQL Server
que crear 2 tablas: Tabla 1 y Tabla 2 y rellenarlas con algunas entradas de la siguiente manera:
Tabla 1:
Col_ID1 ............ ... col_name
1 ......................... ene-11
2 ........ ................. Feb-11
3 ......................... Mar-11
Tabla 2:
Col_ID2 ...... Cuenta ..... Nombre de cuenta ...... Cantidad
1 ............... 121 ......... ..Electricidad ............ 10000
2 ............... 121 ........... Electricidad. ........... 20000
3 ............... 121 ........... Electricidad ............ 30000
1 ............... 122 ........... Teléfono .............. 100
2. .............. 122 ........... Teléfono .............. 200
3 ... ............ 122 ........... Teléfono .............. 300
Estoy creando un Pivote, pero quiero que los nombres de las columnas se generen paramétricamente (en base a las fechas introducidas desde la entrada s creen), y no codificado.
La siguiente consulta funciona bien, pero da sólo unas pocas columnas como SS:
Ene-11 Feb-11 ........... ........ ... Mar-11
10,000.00 20,000.00 ...... ...... 30,000.00
100,00 200,00 ............... .... ....... 300.00
Deseo que la consulta también devuelva las columnas descriptivas, como sigue:
Cuenta ........... Nombre de cuenta ........... Ene-11 ............ Feb-11 .. ............ Mar-11
121 ................. Electricidad ............ ...... 10,000.00 ...... 20,000.00 .......... 30,000.00
122 ................. Teléfono .. ................... 100.00 ........... 200.00 ............. 300.00
¿Alguien podría ayudarme a modificar mi consulta para que pueda lograr mi objetivo?
Esta consulta es una adaptación de la siguiente artículo escrito por el Dr. Andras en septiembre de 2007. http://www.simple-talk.com/community/blogs/andras/archive/2007/09/14/37265.aspx
Alguien comentó que el código podría ser objeto de ataques de inyección y propone utilizar la función QUOTENAME en lugar de la concatenación entre corchetes .
¿Podría explicarme cómo usar Quotename en mi consulta?
Muchas gracias,
Leon Lai .
.
.
Aquí es mi consulta:
------------------------ crear & tabla1 poblar ---------- ----------------------
CREATE TABLE Table1
(Col_ID1 INT,
Col_Name varchar(10))
INSERT INTO Table1 VALUES (1, 'Jan-11')
INSERT INTO Table1 VALUES (2, 'Feb-11')
INSERT INTO Table1 VALUES (3, 'Mar-11')
--------------------- ---- crear & poblar tabla2 ----------------------------------
CREATE TABLE Table2
(Col_ID2 INT,
Account varchar(10),
AccountName varchar(20),
Amount numeric(18,6))
INSERT INTO Table2 VALUES (1, 121, 'Electricity', 10000)
INSERT INTO Table2 VALUES (2, 121, 'Electricity', 20000)
INSERT INTO Table2 VALUES (3, 121, 'Electricity', 30000)
INSERT INTO Table2 VALUES (1, 122, 'Telephone', 100)
INSERT INTO Table2 VALUES (2, 122, 'Telephone', 200)
INSERT INTO Table2 VALUES (3, 122, 'Telephone', 300)
- --------------------------------- crear encabezados de columnas -------------- -----
DECLARE @cols NVARCHAR(2000)
SELECT @cols = STUFF((SELECT DISTINCT TOP 100 PERCENT
'],[' + t2.Col_Name
FROM Table1 AS t2
ORDER BY '],[' + t2.Col_Name
FOR XML PATH('')
), 1, 2, '') + ']'
------------------------------------- create @query --- -------------------
DECLARE @query NVARCHAR(4000)
SET @query = N'SELECT '+
@cols +'
FROM
------------------------ --subquery -----
(SELECT
t1.Col_Name,
t2.Account,
t2.Amount
FROM Table1 AS t1
JOIN Table2 AS t2 ON t1.Col_ID1 = t2.Col_ID2
) p
-------------------- pivote ------------ -------------
PIVOT
(
Sum ([Amount])
FOR Col_Name IN
('+
@cols +')
) AS pvt '
---------------------- exec & gota ----------
EXECUTE(@query)
drop table table1
drop table table2
=== =============================================== ==
Hola Felipe,
Muchas gracias por su respuesta.
Su consulta propuesta funciona sin problemas y genera la pantalla esperada, pero no es exactamente lo que quería.
En primer lugar, gracias por el código: SELECT @cols = isnull (@cols + '' '') + '[' + col_name + ']'
Es más simple y reemplaza mi línea involucrando cosas y ruta xml, aparentemente con el mismo efecto.
Déjame explicarte lo que quiero hacer.
Deseo desarrollar una consulta en Sap Business 1 (Un paquete de contabilidad o llámelo ERP). Sap usa T-sql en Microsoft Server 2008, y tiene su propio generador de consultas. Con muy pocas excepciones, Sap sql es similar a T-sql.
Quiero que mi consulta proporcione una lista de todos los ingresos y gastos mes a mes durante un período de 12 meses.
Sin embargo, yo no quiero que mi encabezados de columna para ser codificados, (ya que esto requeriría me enmendar mi consulta de vez en cuando) de la siguiente manera:
Ene-11, 11-Feb, Mar- 11, abr-11, ..... Dic-11
Más bien, quiero que los encabezados de las columnas se generen dinámicamente a partir de las fechas que el usuario ingrese en la pantalla de entrada.
Como mencioné, la consulta que publiqué en el foro es una versión demasiado simplificada de mi consulta real, que se usa solo a título ilustrativo. La consulta real contiene varias variables y una pantalla de entrada (llamada Query - Cuadro de Criterios de Selección en Sap b1) permite al usuario ingresar una fecha. Es esta fecha la que se usará para determinar dinámicamente los nombres de las columnas.
Esta es la razón por lo que necesitaba este tipo de herramientas complicadas como @cols, @query, etc. pivote
Si de entrada, digo '01 .06.11' (01 jun 2011) en la pantalla de entrada, esta fecha se pasado al sql que determinará los nombres de los títulos de las columnas como sigue:
Jun-11, Jul-11, Aug-11 ..... May-12.
Si otra fecha de entrada, digo '01 .09.10' (01 sep 2010), los títulos de las columnas cambiará a:
Sep-10, 10-Oct, .... 11-Ago
Parece que ha codificado mis encabezados de columna.
¿Podría echar un segundo vistazo a mi consulta y proponer algo que permita que los nombres de las columnas se generen paramétricamente en lugar de codificarse?
Gracias
Leon Lai
Hola, Philip, he posteado una pregunta a tu respuesta Gracias Leon –
¡Esta es una respuesta ridículamente buena! – jTC
Use 'quotename (Col_Name)' en lugar de ''[' + Col_Name + ']''. – jnm2