Lo que vamos a hacer es crear un string que contenga la consulta que vamos a crear con la cantidad de valores que nosotros queramos en forma dinamica
me refiero si tenemos esto
para pivotear esto la documentacion dice que se debe hacer de la siguiente forma
link :
--------------------------------------
ejemplo link:
DaysToManufacture----AverageCost
0-----------------------------5.0885
1-----------------------------223.88
2-----------------------------359.1082
4-----------------------------949.4105
para pivotear
SELECT 'AverageCost' AS Cost_Sorted_By_Production_Days,
[0], [1], [2], [3], [4]
FROM
(SELECT DaysToManufacture, StandardCost
FROM Production.Product) AS SourceTable
PIVOT
(
AVG(StandardCost)
FOR DaysToManufacture IN ([0], [1], [2], [3], [4])
) AS PivotTable;
el resultado será
Cost_Sorted_By_Production_Days 0 1 2 3 4
AverageCost 5.0885 223.88 359.1082 NULL 949.4105
-----------------------------------------------------------
pero si se fijan ahi se debe incluir todos los valores de los dias, es decir que si existen 1000 dias se deben listar de 1 a 1000 días ([0], [1], [2], [3], [4]....[1000]), para hacer esto dinamico y si vemos que no solo pueden ser dias, sino, tipos de documentos, fechas, nombre, cuentas, etc, etc, recordar los nombre y escriibirlos uno a uno no es muy agradable entonces podemos hacer lo siguiente para crear dinamicamente el select que nos mostrará nuestro valores pivoteados tal como queremos.
continuando con mi ejemplo
el query que creará nuestro query es el siguiente:
DECLARE @Tipo VARCHAR(10) -- el largo 10 corresponde con el largo maximo del valor tipo que se pivoteara, si es mayor se debe aumentar
DECLARE @PVT VARCHAR(MAX)
DECLARE @PVT1 VARCHAR(MAX)
DECLARE @PVT2 VARCHAR(MAX)
SELECT @Tipo = MIN(Tipo) FROM TipoValor WHERE Tipo>'' -- select al menor tipo
SET @PVT1 = '' --en esta variable guardaremos los tipos entre comillas ''
SET @PVT2 = '' --en esta variable guardaremos los tipos entre corchetes []
--crearemos un ciclo para recorrer todos los tipos
WHILE NOT(@Tipo IS NULL)-- cuando se acaben los tipos de fechas
BEGIN
IF @PVT1 <> ''
SET @PVT1 = @PVT1 + ', '
SET @PVT1 = @PVT1+''''+@Tipo+'''' --tipos entre comillas
IF @PVT2 <> ''
SET @PVT2 = @PVT2 + ', '
SET @PVT2 = @PVT2+'['+@Tipo+']' --tipos entre corchetes
SELECT @Tipo = MIN(Tipo) FROM TipoValor WHERE Tipo > @Tipo --buscamos el siguente tipo de fechas mayor al anterior
END -- fin del ciclo
-- en la variable @PVT guadaremos como string el query del pivot
SELECT @PVT = 'SELECT Nombre,
'+@PVT2+ --tipos con corchetes
' FROM (SELECT
Nombre
Tipo,
Valor FROM
TipoValor WHERE
Tipo IN
( '+@PVT1+' )) as FEOC --tipos con comillas
PIVOT (MAX(Valor) -- el MAX es por si existe mas de un Tipo, se puede Sumar o agrgar cualquier funcion de agregacion
FOR Tipo IN (
'+@PVT2+' )) as P
GROUP BY
Nombre, '+@PVT2
SELECT @PVT -- Vemos el string donde esta el query del PIVOT completo
EXEC(@PVT) -- con el comando EXEC podemos ejecutar el string, que nos retornara el resultado que queremos
Todo esto nos deberia retornar los siguiente:
asi logramos agrupar por nombre, y pivoteamos el valor y los tipos, donde hay que notar el tipo T3 y que se repite para los nombre nom1 y nom3, donde podemos ver facilmente cuales típos y que valor tiene cada nombre
esta es la mejor opcion de mostrar la informacion, porque la otra opcion y que no es buena de mostrar es la siguiente
Select Nombre, Tipo, Valor from TipoValor order by Nombre
que mostrara algo asi como que no es lo optimo.
7 comentarios:
El @PVT siempre estara en comillas? porque yo he intentado enviarle parametros (lo encerre en un procedure). Le envio por ejemplo @agencia='Lima'
Pero al momento de insertarlo al @PVT aparece como solo Lima, borrandose la comilla simple. Sabes de alguna forma de solucionar esto?
Hola necesito si me puedes ayudar con mi problema que no doy con la solucion, tiene algo que ver con pivot pero no se muy bien como utilizarlo.-
El tema es el siguiente:
1- Tengo que mostrar el resultado de a 31 columas, en la primer columna UNIDNEGO y en las siguientes 30 las FECHAS.-
estos son los datos:
SELECT UNIDNEGO, CLIENTE, A_FECHAESTADIA FROM PEDIDOS
UNIDNEGO CLIENTE A_FECHAESTADIA
--------- ---------- -----------------------
417 010001159 2011-12-18 00:00:00.000
417 010001159 2011-12-19 00:00:00.000
417 010001159 2011-12-20 00:00:00.000
417 010001159 2011-12-21 00:00:00.000
301 010001158 2011-12-27 00:00:00.000
301 010001158 2011-12-28 00:00:00.000
301 010001158 2011-12-29 00:00:00.000
...
tendria que quedar algo asi:
UNIDNEGO 2011-12-18 2011-12-19 2011-12-20 2011-12-21 2011-12-22 2011-12-23 2011-12-24 2011-12-25 2011-12-26 2011-12-27 2011-12-28 2011-12-29 ...
--------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------- ...
301 010001158 010001158 010001158 ...
417 010001159 010001159 010001159 010001159 ...
desde ya gracias
Hello thегe! Do you use Twittеr? ӏ'd like to follow you if that would be ok. I'm
ԁefinitely enјoуing your blog and lοοκ forward to new postѕ.
Ηave a look at my ωeb site cialis prix
Buen dia. Mi problema es que no logro que corra el query. Tengo 22 sitios de acopio y requiero que esos sitios de acopio sean los encabezados. Me sae el error de Oracle: ORA-01748: only simple column names allowed here
Les agradezco su ayuda.
SELECT * FROM (SELECT PSA_ANO,PSA_MES,PSA_VALOR FROM (
SELECT c.PSA_ANO, c.PSA_MES, c.PSA_VALOR
FROM DIES_SITIOS_ACOPIO b INNER JOIN DIES_PRECIOS_SITIOS_ACOPIO c ON (b.ACO_ID = c.ACO_ID)))
PIVOT (abs(PSA_VALOR) FOR b.ACO_DESCRIPCION IN (SELECT ACO_DESCRIPCION FROM DIES_SITIOS_ACOPIO))
Agrego un detalle en el código gracias al amigo Luis Hilario que me ha ayudado a encontrar este error.
Se agrega una coma luego de los campos nombre tanto en el Select como en el Group By.
Un Saludo
-- ME SALIO, GRACIAS A LA AYUDA DE SERGIO VALENZUELA
DECLARE @Tipo VARCHAR(16)
DECLARE @PVT VARCHAR(MAX)
DECLARE @PVT1 VARCHAR(MAX)
DECLARE @PVT2 VARCHAR(MAX)
SELECT @Tipo = MIN(code) FROM yconta WHERE code >'' -- select al menor tipo
SET @PVT1 = '' --en esta variable guardaremos los tipos entre comillas ''
SET @PVT2 = '' --en esta variable guardaremos los tipos entre corchetes []
--crearemos un ciclo para recorrer todos los tipos
WHILE NOT(@Tipo IS NULL)
BEGIN
IF @PVT1 <> ''
SET @PVT1 = @PVT1 + ', '
SET @PVT1 = @PVT1+''''+@Tipo+''''
IF @PVT2 <> ''
SET @PVT2 = @PVT2 + ', '
SET @PVT2 = @PVT2+'['+@Tipo+']'
SELECT @Tipo = MIN(code) FROM yconta WHERE code > @Tipo
END
-- en la variable @PVT guadaremos como string el query del pivot
SELECT @PVT = 'SELECT codEsp
,'+@PVT2+
' FROM (SELECT codEsp,code, tot FROM yconta WHERE
code IN
( '+@PVT1+' )) as FEOC --tipos con comillas
PIVOT (MAX(tot)
FOR code IN (
'+@PVT2+' )) as P
GROUP BY
codEsp, '+@PVT2
SELECT @PVT
EXEC(@PVT)
Saludos a todos, deseo hacer una pregunta y pretendo ser lo mas claro posible.
Tengo una tabla llamada "Asistencias" con los siguientes registros:
MATRICULA NOMBRE HORA FECHA
1 Alumno X 17:02:00 23/03/2016
1 Alumno X 17:00:00 24/03/2016
1 Alumno X 17:06:00 25/03/2016
2 Alumno Y 17:01:00 23/03/2016
2 Alumno Y 17:03:00 24/03/2016
3 Alumno Z 17:05:00 23/03/2016
3 Alumno Z 17:04:00 24/03/2016
3 Alumno Z 17:08:00 25/03/2016
En esta tabla, un Alumno X ingresa una Hora X en una Fecha X; este alumno puede ingresar N Asistencias a esta misma tabla, siempre y cuando no sean el mismo día. Hasta aquí todo bien.
Ahora, para poder generar un reporte, necesito convertir las filas de este alumno X a columnas segun el rango de fechas solicitadas. No tuve problema en generar la siguiente consulta:
------------------------------
Select NOMBRE, [2016-03-23] as '2016-03-23', [2016-03-24] as '2016-03-24', [2016-03-25] as '2016-03-25'
from(Select NOMBRE,FECHA,HORA from Asistencias)
pvt
pivot(min(HORA) for [FECHA] in ([2016-03-23],[2016-03-24],[2016-03-25])) as Asistir
order by NOMBRE
------------------------------
Obteniendo el siguiente resultado:
NOMBRE 2016-03-23 2016-03-24 2016-03-25
Alumno X 17:02:00 17:00:00 17:06:00
Alumno Y 17:01:00 17:03:00 NULL
Alumno Z 17:05:00 17:04:00 17:08:00
El resultadol es excelente, ya que es justo lo que necesitaba, que aparezca un reporte tomando un alumno por fila y que las fechas ingresadas se convirtieran en columnas, logrando asi registrar a detalle la hora en la que cada alumno tomó o no tomó asistencia (null).
**** Problema ****
Ahora que he obtenido lo que quiero, deseo convertir esta consulta en un PROCEDIMIENTO DINAMICO y que a éste NO se le ingresen manualmente los valores de las N fechas, sino que se ingresen solo dos valores (fechaInicial y fechaFinal ) y que estos dos valores generen las columnas necesarias en dicho reporte (algo como un arreglo).
Es decir, si el Procedimiento recibe:
fechaInicial = '01/01/2016'
fechaFinal = '10/01/2016'
Entonces, se deberán generar 10 Columnas cada una con la fecha correspondiente.
Solo deseo que mi procedimiento sea dinámico y que sea capaz de recibir las dos fechas (inicial y final) y generar así las columnas necesarias segun el rango de estas fechas.
Espero haber sido lo suficientemente claro. Agradezco a todos su atención
Publicar un comentario