Usando SQL para obtener los datos de las filas anteriores

Tengo un requisito en el que necesito obtener datos de la fila anterior para usarlos en un cálculo para dar un estado a la fila actual. Es una tabla de historia. La fila anterior me permitirá saber si un dato ha cambiado en un campo de fecha.

He buscado usando cursores y parece un poco complicado. ¿Es esta la mejor manera de hacerlo?

También intenté asignar un valor a un nuevo campo ...

newField = (Seleccione field1 de Table1 donde "fila anterior") fila anterior es donde parece que me atasco. No puedo averiguar cómo seleccionar la fila debajo de la fila actual.

Estoy usando SQL Server 2005

Gracias de antemano.

preguntado el 16 de mayo de 11 a las 18:05

"anterior" como ?? Según qué criterios, qué orden de clasificación, qué ORDER BY ¿¿¿declaración??? SQL Server no tiene un "pedido" per se; solo obtiene un pedido cuando especifica un ORDER BY cláusula .... -

¿Puede proporcionar la estructura de la mesa? No es simple en SQL Server 2005, pero puede lograrlo usando Row_Number y Self Join ..... -

Está atascado porque está intentando colocar la fila debajo de la fila actual. Todo el mundo sabe que las filas anteriores son arriba la fila actual. -

He buscado usando cursores y parece un poco complicado. ¿Es esta la mejor manera de hacerlo? casi siempre no -

¿Cómo se define "fila anterior"? ¿Está preguntando por la fila cuya clave principal es el siguiente valor más alto, o hay un campo de fecha que rastrea el orden de las filas? Deberá proporcionar un poco más de información. -

3 Respuestas

-- Test data
declare @T table (ProjectNumber int, DateChanged datetime, Value int)
insert into @T 
  select 1, '2001-01-01', 1 union all
  select 1, '2001-01-02', 1 union all
  select 1, '2001-01-03', 3 union all
  select 1, '2001-01-04', 3 union all
  select 1, '2001-01-05', 4 union all
  select 2, '2001-01-01', 1 union all
  select 2, '2001-01-02', 2

-- Get CurrentValue and PreviousValue with a Changed column
;with cte as
(
  select *,
    row_number() over(partition by ProjectNumber order by DateChanged) as rn
  from @T
)
select
  C.ProjectNumber,
  C.Value as CurrentValue,
  P.Value as PreviousValue,
  case C.Value when P.Value then 0 else 1 end as Changed
from cte as C
  inner join cte as P
    on C.ProjectNumber = P.ProjectNumber and
       C.rn = P.rn + 1

-- Count the number of changes per project  
;with cte as
(
  select *,
    row_number() over(partition by ProjectNumber order by DateChanged) as rn
  from @T
)
select
  C.ProjectNumber,
  sum(case C.Value when P.Value then 0 else 1 end) as ChangeCount
from cte as C
  inner join cte as P
    on C.ProjectNumber = P.ProjectNumber and
       C.rn = P.rn + 1
group by C.ProjectNumber

contestado el 17 de mayo de 11 a las 01:05

Vaya, esto parece prometedor. Poniéndolo en su lugar ahora. ¡Gracias! - Gallinero

¡¡¡Puse esto en su lugar y funcionó muy bien !!! Veo las habilidades / conceptos que me faltaban. El CTE funciona muy bien. He usado tablas temporales y probé una vista, pero el CTE es mucho más fácil. El CTE le permite conectar la mesa consigo misma, lo cual es muy valioso. Y combinado con row_numbers funciona muy bien. Gracias por tu ayuda. - Gallinero

Esto realmente depende de lo que le indique que una fila es una "Fila anterior". sin embargo, una autounión debería hacer lo que quieras:

select *
from Table1 this
  join Table2 prev on this.incrementalID = prev.incrementalID+1

contestado el 16 de mayo de 11 a las 22:05

Cada fila no tiene un ID único. ¿IncrementalID es algo que está integrado en la tabla? - Gallinero

Además, los datos con los que estoy trabajando son un subconjunto de la tabla completa, por lo que si había una ID incremental, el subconjunto puede no estar en orden secuencial. - Gallinero

Si tiene la siguiente tabla

CREATE TABLE MyTable (
   Id            INT NOT NULL,
   ChangeDate    DATETIME NOT NULL,
   .
   .
   .
)

La siguiente consulta devolverá el registro anterior para cualquier registro de MyTable.

SELECT tbl.Id,
       tbl.ChangeDate,
       hist.Id,
       hist.ChangeDate
  FROM MyTable tbl 
       INNER JOIN MyTable hist
        ON hist.Id = tbl.Id 
       AND hiost.ChangeDate = (SELECT MAX(ChangeDate) 
                                 FROM MyTable sub 
                                WHERE sub.Id = tbl.Id AND sub.ChangeDate < tbl.ChangeDate)

contestado el 16 de mayo de 11 a las 22:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.