2011-01-12 10 views
5

Teniendo en cuenta esta tabla:SQL - secuencial problema de actualización - actualización con los datos de actualización

create table x (id int, total int, diff int) 

Y estos datos:

[1, 100, 20] 
[2, null, 30] 
[3, null, -15] 
[4, null, 4] 
… 

necesito para calcular la columna "total" de acuerdo a la fila anterior .

Eso significa que al final de los datos debe ser similar a lo siguiente:

[1, 100, 20] 
[2, 120, 30] 
[3, 150, -15] 
[4, 135, 4] 
… 

¿Cuál es la forma más eficiente de hacer eso?

+0

¿Cuál es la lógica aquí? – nan

+0

?? No tiene ningún sentido ... el valor en la fila 2 es 120, que es (100 + 20) desde la fila 1, ¿verdad? Entonces, ¿por qué el valor está en la fila 3 105? ¿No debería ser 150 (120 + 30)? ¿Por qué el valor está en la fila 4 101? ¿No debería ser 90 (105 - 15)? –

+0

Esos totales no parecen tener ningún sentido. –

Respuesta

2

OK, aquí hay otra opción. Agregar como una respuesta separada ya que es un enfoque completamente diferente.

La suposición con esto es que no hay lagunas en los ID, esto puede no ser realista, pero demuestra el enfoque. Si hay lagunas en los ID, entonces solo debería tomar un pequeño ajuste en JOIN.

DECLARE @Data TABLE (ID INTEGER PRIMARY KEY, Total INTEGER, Diff INTEGER) 
INSERT @Data VALUES (1, 100, 20) 
INSERT @Data VALUES (2, NULL, 30) 
INSERT @Data VALUES (3, NULL, -15) 
INSERT @Data VALUES (4, NULL, 4) 

DECLARE @PreviousTotal INTEGER 
SELECT @PreviousTotal = Total 
FROM @Data 
WHERE ID = 1 

UPDATE d 
SET @PreviousTotal = d.Total = @PreviousTotal + d2.Diff 
FROM @Data d 
    JOIN @Data d2 ON d.ID = d2.Id + 1 

SELECT * FROM @Data 
0

En el supuesto de que el resultado de la muestra es incorrecto, y así debería ser marc_s publicado en su comentario, puede hacerlo de esta manera:

  • Para el primer registro:

    INSERT into X Values(1, 100, 20) 
    
  • Luego, para todos los demás (con los valores id y diff correspondientes en la primera y última columna):

No es tan bueno, pero funciona.

+0

Debe ser una actualización. las filas ya están allí. –

+0

También me di cuenta de eso, pero solo después de publicar esto ... Así que siéntete libre de ignorarlo. :) – MicSim

2

No estoy muy seguro sobre el rendimiento de esta tbh, por lo que debe probarlo, pero esta es una manera. Estoy seguro de que hay otras formas, así que esta es una posibilidad. Como digo, el rendimiento sería mi principal preocupación.

DECLARE @Data TABLE (ID INTEGER PRIMARY KEY, Total INTEGER, Diff INTEGER) 
INSERT @Data VALUES (1, 100, 20) 
INSERT @Data VALUES (2, NULL, 30) 
INSERT @Data VALUES (3, NULL, -15) 
INSERT @Data VALUES (4, NULL, 4) 

DECLARE @StartingTotal INTEGER 
SELECT @StartingTotal = Total FROM @Data WHERE ID = 1 

UPDATE d 
SET d.Total = @StartingTotal + TotalDiff 
FROM @Data d 
    CROSS APPLY (SELECT SUM(Diff) TotalDiff FROM @Data d2 WHERE d2.ID < d.ID) x 
WHERE d.Total IS NULL 

SELECT * FROM @Data 
0

Normalmente no recomendaría utilizar cursores, pero en este caso podría ser una buena opción. Si te preocupa el rendimiento, debes probar las respuestas dadas aquí para descubrir qué es lo más rápido para ti. La mejor solución puede variar según la cantidad de filas en la tabla.

declare @T as table (id int, total int, diff int) 

insert into @T values (1, 100, 20) 
insert into @T values (2, null, 30) 
insert into @T values (3, null, -15) 
insert into @T values (4, null, 4) 

declare @id int 
declare @diff int 
declare @total int 

select @total = total 
from @T 
where id = 1 

declare cT cursor for select id, diff from @T order by id 

open cT 
fetch next from cT into @id, @diff 
while (@@FETCH_STATUS <> -1) 
begin 
    update @T 
    set total = @total 
    where id = @id 

    set @total = @total + @diff 

    fetch next from cT into @id, @diff 
end 
close cT 
deallocate cT 

select * 
from @T 
Cuestiones relacionadas