Principales respuestas
creacion de cursor para suma

Pregunta
-
hola a todos, quisiera hacer un cursor o algo similar para poder obtener totales por dia. esta es mi tabla create table tabla1 (
Fecha datetime not null,
monto float not null)
insert into tabla1 values('20130430','8250'),
('20130501','1050'),
('20130502','850'),
('20130502','700'),
('20130503','1300'),
('20130503','1100'),
('20130503','1250'),
('20130504','1100')
y quiero obtener este resultado, donde 0 es el ultimo dia del mes anterior y se va haciendo como un subtotal en el campo monto. espero su ayuda.
maculdes
Respuestas
-
Cual es la version de SQL Server que usas?
Si usas una version menor a la 2012, entonces te tocara usar uno de los sgtes metodos:
- Cursor
- Union de la tabla consigo misma
- Query correlacionado
En dependencia del numero de filas que contenga la tabla, asi como el numero de fechas y filas por fecha asi sera el desempeño de cada opcion. Hasta la version 2008 R2, el uso de cursores para solucionar este problema solia ser el de mejor desempeño.
La cosa cambio en la version 2012 con la expansion al soporte de la clausula OVER y las llamadas funciones de ventana.
-- query correlacionado SELECT A.fecha, (ROW_NUMBER() OVER(ORDER BY A.fecha) - 1) AS rn, SUM(A.monto) AS monto_fecha, ( SELECT SUM(B.monto) FROM tabla1 AS B WHERE B.fecha < A.fecha ) + SUM(A.monto) AS monto_corriente FROM tabla1 AS A GROUP BY A.fecha ORDER BY A.fecha; GO
Si cuentas con la version SS 2012, entonces seria tan simple como:
SELECT fecha, (ROW_NUMBER() OVER(ORDER BY fecha) - 1) AS rn, SUM(monto) AS monto_fecha, SUM(SUM(monto)) OVER( ORDER BY fecha ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS monto_corriente FROM tabla1 AS A GROUP BY fecha ORDER BY fecha; GO
Tener un indice cubierto por [fecha] ayudaria con el desempeño para ambas soluciones.
AMB
Some guidelines for posting questions...
- Editado HunchbackMVP miércoles, 26 de junio de 2013 13:07 correccion
- Marcado como respuesta maculdes jueves, 4 de julio de 2013 15:30
Todas las respuestas
-
-
-
Buenas
claro, le haces el group by para agrupar por fecha, si no quieres mostrar la fecha y solo quieres mostrar el ID
no se...
quizá esto¿?
select Sum(monto), (row_number() over (order by fecha asc) - 1) as Dia
from tabla1 group by fecha
Ahí tienes, la select que tu pides mas o menos :-)
jajajajajaja, si no es eso lo que quieres, dame un poco mas de luz por que no me acabo de enterar xDDD
Edito: ¿el 2600 del día 2 de donde lo sacas?
Saludos!
- Editado Jnavero martes, 25 de junio de 2013 22:01 Edito - Aclaracion
-
-
Esto consigue el resultado que buscas, solo tienes que ver para calcular o setear las fechas de manera correcta
with cte as ( select Fecha, sum(monto) suma from dbo.tabla1 where fecha >= '20130501' group by Fecha ) select day(Fecha) dia, sum(monto) Monto from dbo.tabla1 where fecha = '20130430' group by Fecha union all select day(cte.Fecha) dia, sum(cte2.suma) Monto from cte join cte cte2 on cte.Fecha >= cte2.Fecha group by cte.Fecha
- Propuesto como respuesta Carlos Sacristan miércoles, 26 de junio de 2013 9:10
-
Hola, yo lo haria con un inner join triangular para hacer el acumulativo si tienes 2008 r2 y si es 2012 con over partition,
en 2008 que te vale para los dos seria asi:
SELECT v1.DIA ,SUM(v2.MONTO) AS MONTO_ACUMULADO FROM( SELECT DAY(FECHA) AS DIA ,MONTH(FECHA) AS MES ,YEAR(FECHA) AS ANO ,MONTO FROM TABLA1 ) AS V1 LEFT OUTER JOIN ( SELECT DAY(FECHA) AS DIA ,MONTH(FECHA) AS MES ,YEAR(FECHA) AS ANO ,MONTO FROM TABLA1 ) AS V2 ON V1.ANO = V2.ANO AND V1.MES*100+v1.DIA>= V2.MES*100+V2.DIA
GROUP BY V1.DIACon esta query tendrias para cada dia en el primer dia el valor de monto para el dia 2 tendrias el valor de dia 2 + dia 1, para el dia 3 tendraias lo del1+2+3 y asi sucesivamente.
Si quieres que el ultimo dia del mes te ponga 0 con un case en dia lo tendrias.
Saludos.
- Editado Bud_Spencer miércoles, 26 de junio de 2013 8:30 me faltaba un alias
- Propuesto como respuesta Atir58 miércoles, 26 de junio de 2013 20:37
- Votado como útil Atir58 miércoles, 26 de junio de 2013 20:37
- Propuesto como respuesta Atir58 viernes, 19 de julio de 2013 14:20
-
Alberto, tu solución no es válida. Fíjate en los resultados que devuelve y te darás cuenta el por qué.
Aunque la solución propuesta por Ronald sí que devuelve los datos correctos, existen más opciones, y dependiendo de la versión de SQL Server que tengas puede llegar a ser muy sencilla. De hecho, ese escenario es muy común y se conoce como "running aggregates", por lo que puedes encontrar múltiples ejemplos en la web, sin ir más lejos aquí [http://stackoverflow.com/questions/860966/calculate-a-running-total-in-sqlserver]
-
Cual es la version de SQL Server que usas?
Si usas una version menor a la 2012, entonces te tocara usar uno de los sgtes metodos:
- Cursor
- Union de la tabla consigo misma
- Query correlacionado
En dependencia del numero de filas que contenga la tabla, asi como el numero de fechas y filas por fecha asi sera el desempeño de cada opcion. Hasta la version 2008 R2, el uso de cursores para solucionar este problema solia ser el de mejor desempeño.
La cosa cambio en la version 2012 con la expansion al soporte de la clausula OVER y las llamadas funciones de ventana.
-- query correlacionado SELECT A.fecha, (ROW_NUMBER() OVER(ORDER BY A.fecha) - 1) AS rn, SUM(A.monto) AS monto_fecha, ( SELECT SUM(B.monto) FROM tabla1 AS B WHERE B.fecha < A.fecha ) + SUM(A.monto) AS monto_corriente FROM tabla1 AS A GROUP BY A.fecha ORDER BY A.fecha; GO
Si cuentas con la version SS 2012, entonces seria tan simple como:
SELECT fecha, (ROW_NUMBER() OVER(ORDER BY fecha) - 1) AS rn, SUM(monto) AS monto_fecha, SUM(SUM(monto)) OVER( ORDER BY fecha ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS monto_corriente FROM tabla1 AS A GROUP BY fecha ORDER BY fecha; GO
Tener un indice cubierto por [fecha] ayudaria con el desempeño para ambas soluciones.
AMB
Some guidelines for posting questions...
- Editado HunchbackMVP miércoles, 26 de junio de 2013 13:07 correccion
- Marcado como respuesta maculdes jueves, 4 de julio de 2013 15:30