2011-11-21 19 views
7

Duplicar posible:
How do I calculate a running total in SQL without using a cursor?¿Obtiene la suma de todos los valores anteriores? - Total hasta ahora?

Es un poco difícil de explicar, así que voy a mostrar lo que quiera con un ejemplo:

digamos que tenemos el siguiente cuadro llamado MonthProfit:

[MonthId][Profit] 
1, 10 -- January 
2, 20 -- February 
3, 30 
4, 40 
5, 50 
6, 60 
7, 70 
8, 80 
9, 90 
10, 100 
11, 110 
12, 120 -- December 

La columna profit representa el beneficio de ese mes.

Sin embargo, si tenemos 10 ganancias en enero y 20 de febrero, en febrero tenemos un beneficio total de 30.

por lo que me gustaría crear una vista que muestra lo siguiente:

[MonthId][Profit][ProfitTotal] 
1, 10, 10 -- January 
2, 20, 30 -- February 
3, 30, 60 
4, 40, 100 
5, 50, 150 
6, 60, 210 
7, 70, 280 
8, 80, 360 
9, 90, 450 
10, 100, 550 
11, 110, 660 
12, 120, 780 -- December 

lo que hice ahora para resolverlo, es una vista como esta:

SELECT [MonthId] 
     ,[Profit] 
     , (SELECT SUM([Profit]) 
     FROM MonthProfit 
     WHERE [MonthId] <= outer.[MonthId]) as ProfitTotal 
FROM MonthProfit as outer 

sin embargo, supongo que esto es bastante lento, ya que tiene que contar todo, todo el tiempo, y no parece cinco Elegante para mí. ¿Existe una forma correcta de hacer esto?

+2

también http://stackoverflow.com/questions/814054/complicated-sql-query-for-a-running-total-column – JNK

+2

Sólo la búsqueda de "Ejecución de SQL total" y obtendrá muchos éxitos en esto. – JNK

Respuesta

3

me han tratado aquí un pequeño ejemplo para su referencia esto genera los resultados según las necesidades

CREATE TABLE [dbo].[tbl_TotalPrevious](
[id] [int] IDENTITY(1,1) NOT NULL, 
[name] [varchar](50) NOT NULL, 
[values] [bigint] NOT NULL) 

insertar datos en la TABLA

insert into tbl_TotalPrevious values ('A', 10) 
insert into tbl_TotalPrevious values ('B', 20) 
insert into tbl_TotalPrevious values ('C', 10) 
insert into tbl_TotalPrevious values ('D', 10) 
insert into tbl_TotalPrevious values ('E', 10) 
insert into tbl_TotalPrevious values ('F', 10) 
insert into tbl_TotalPrevious values ('G', 10) 
insert into tbl_TotalPrevious values ('H', 10) 
insert into tbl_TotalPrevious values ('I', 10) 
insert into tbl_TotalPrevious values ('J', 10) 
insert into tbl_TotalPrevious values ('K', 10) 
insert into tbl_TotalPrevious values ('L', 10) 
insert into tbl_TotalPrevious values ('M', 10) 
insert into tbl_TotalPrevious values ('N', 10) 
insert into tbl_TotalPrevious values ('O', 10) 
insert into tbl_TotalPrevious values ('P', 10) 
insert into tbl_TotalPrevious values ('Q', 10) 
insert into tbl_TotalPrevious values ('R', 10) 
insert into tbl_TotalPrevious values ('S', 10) 
insert into tbl_TotalPrevious values ('T', 10) 
insert into tbl_TotalPrevious values ('U', 10) 
insert into tbl_TotalPrevious values ('V', 10) 
insert into tbl_TotalPrevious values ('W', 10) 
insert into tbl_TotalPrevious values ('X', 10) 
insert into tbl_TotalPrevious values ('Y', 10) 

crear una función, por ejemplo.

ALTER FUNCTION testtotal 
(
    @id int 
) 
RETURNS int 
AS 
BEGIN 
    DECLARE @Result int 
    SELECT @Result = (SELECT SUM([values]) 
     FROM tbl_TotalPrevious 
     WHERE [id] <= @id) 

    RETURN @Result 

END 
GO 

resultados generados a partir una única consulta

SELECT [id],[values], (dbo.testtotal(id)) as TotalVals FROM tbl_TotalPrevious 

HOPE ARRIBA resuelve su FIN CON EL problema de tiempo y genera los datos más rápido como sea necesario.

RESULTS IMAGE

+1

¿No hace exactamente lo mismo que mi subconsulta? ¿Solo encapsulado en una función? –

+0

Pero hacer esto aún disminuirá el tiempo y la exploración de la tabla debido a una función. pero creo que deberías implementar y probar tu plan de ejecución para los datos en vivo que tienes. – Murtaza

-1

Parece ser una opción no muy elegante, pero funciona correctamente.

Si quieres mejorar, tienes varias opciones:

  1. presentar una tercera columna de la tabla (el ProfitTotal) que será actualizado (Disparador) de los valores de inserción/actualización o si desea hacerla en seleccionar;
  2. Crear índice para hacerlo más rápido;
  3. Actualice las estadísticas de la tabla.
0

Pruebe algo como esto a continuación, a primera vista se ve bien :-).

create table #tab ([MonthId] int, [Profit] int) 

insert into #tab select 1, 10 -- January 
insert into #tab select 2, 20 -- February 
insert into #tab select 3, 30 
insert into #tab select 4, 40 
insert into #tab select 5, 50 
insert into #tab select 6, 60 
insert into #tab select 7, 70 
insert into #tab select 8, 80 
insert into #tab select 9, 90 
insert into #tab select 10, 100 
insert into #tab select 11, 110 
insert into #tab select 12, 120 -- December 

select t.*, t3.total 
from #tab t 
join (
    select t1.monthId, 
     sum(t2.profit) as total 
    from #tab t1 
    join #tab t2 on t1.monthId >= t2.monthId 
    group by t1.monthId 
) t3 on t.monthId = t3.monthId 
0
declare @MonthProfit table 
(
    [MonthId] int, 
    [Profit] int 
) 

insert into @MonthProfit values 
(1, 10),(2, 20),(3, 30),(4, 40), 
(5, 50),(6, 60),(7, 70),(8, 80), 
(9, 90),(10, 100),(11, 110),(12, 120) 

;with C as 
(
    select M.MonthId, 
     M.Profit 
    from @MonthProfit as M 
    where M.MonthId = 1 
    union all 
    select M.MonthId, 
     C.Profit + M.Profit 
    from @MonthProfit as M 
    inner join C 
     on M.MonthId = C.MonthId + 1 
) 
select C.MonthId, 
     C.Profit 
from C 
order by C.MonthId 
Cuestiones relacionadas