none
creacion de cursor para suma RRS feed

  • 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

    martes, 25 de junio de 2013 20:57

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
    miércoles, 26 de junio de 2013 12:53

Todas las respuestas

  • para este caso, no es necesario cursor ni nada, con un select sum te sirve

    algo similar a esto:

    SELECT SUM(monto), Fecha
     FROM tabla1
     GROUP BY Fecha
    Saludos
    martes, 25 de junio de 2013 21:20
  • ahi lo agrupa por fecha, mas no hace suma acumulativa

    maculdes

    martes, 25 de junio de 2013 21:26
  • 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
    martes, 25 de junio de 2013 21:59
  • es la suma de los dias

    2013-05-01-->1050

    2013-05-02-->850

    2013-05-02-->700


    maculdes

    martes, 25 de junio de 2013 23:13
  • 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
    martes, 25 de junio de 2013 23:59
  • 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.DIA

    Con 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
    miércoles, 26 de junio de 2013 8:22
  • 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]

    miércoles, 26 de junio de 2013 9:10
  • 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
    miércoles, 26 de junio de 2013 12:53