2010-10-21 12 views
6

Tengo los datos del sensor en una tabla en la forma:derivada discreta en SQL

Time  Value 
10  100 
20  200 
36  330 
46  440 

me gustaría tirar del cambio en los valores para cada período de tiempo. Idealmente, me gustaría llegar:

Starttime Endtime Change 
10  20  100 
20  36  130 
36  46  110 

Mis conocimientos de SQL son bastante rudimentarios, por lo que mi inclinación es para tirar todos los datos a un script que procesa y luego empuje de nuevo a la nueva tabla, pero Pensé que podría preguntar si había una forma elegante de hacer esto en la base de datos.

+0

Sería una excelente pregunta para la entrevista: Trivial de formular pero no trivial de arreglar. –

+0

+1 por el hecho de que eres lo suficientemente inteligente como para no solo hacerlo de la manera que ya lo sabes y hacer la pregunta. – Kuberchaun

Respuesta

1
Select a.Time as StartTime 
    , b.time as EndTime 
    , b.time-a.time as TimeChange 
    , b.value-a.value as ValueChange 
FROM YourTable a 
Left outer Join YourTable b ON b.time>a.time 
Left outer Join YourTable c ON c.time<b.time AND c.time > a.time 
Where c.time is null 
Order By a.time 
+0

Esto me parece un poco ineficiente. ¿Tiene sentido hacer 2 uniones cuando una unión sería suficiente? Vea esta respuesta http://stackoverflow.com/questions/6299950/sql-difference-between-rows –

0

En primer lugar, agregaría una columna de identificación a la tabla para que tenga algo que previsiblemente aumenta de una fila a otra.

Entonces, me gustaría probar la siguiente consulta:

SELECT t1.Time AS 'Starttime', t2.Time AS 'Endtime', 
    (t2.Value - t1.Value) AS 'Change' 
FROM SensorData t1 
INNER JOIN SensorData t2 ON (t2.id - 1) = t1.id 
ORDER BY t1.Time ASC 

Voy a crear una tabla de prueba para probar esto para mí, así que no sé si todavía funciona, pero es digno de un tiro!

actualización fijo con un tema de menor importancia (El cambio es una palabra protegida y tuvo que ser citado), pero probado y funciona! Produce exactamente los resultados definidos anteriormente.

+0

Esto solo funcionará si las filas se insertan en orden (por startTime) Y nunca se eliminará ninguna fila; borrar una fila dará como resultado un espacio para que t2.id - t1.id sea> 1 – Andy

+0

De hecho, tienes razón, pero dada la naturaleza de los datos (es decir, provenientes de un sensor), esperaría que las filas estén correctas una fila secuencial y una eliminada serían poco probables (supongo) ya que efectivamente sería una brecha en los datos. –

2
Select a.Time as StartTime, b.time as EndTime, b.time-a.time as TimeChange, b.value-a.value as ValueChange 
FROM YourTable a, YourTable b 
WHERE b.time = (Select MIN(c.time) FROM YourTable c WHERE c.time>a.time) 
+0

Probado esto en mi copia de la tabla y también funciona. Me gusta la adición del cambio de hora, así como el cambio de valor :) –

+0

También veo mi otra respuesta, evita la subconsulta. – Andy

0

hace este trabajo?

WITH T AS 
(
SELECT [Time] 
    , Value 
    , RN1 = ROW_NUMBER() OVER (ORDER BY [Time]) 
    , RN2 = ROW_NUMBER() OVER (ORDER BY [Time]) - 1 
FROM SensorData 
) 
SELECT 
    StartTime = ISNULL(t1.[time], t2.[time]) 
, EndTime = ISNULL(t2.[time], 0) 
, Change = t2.value - t1.value 

FROM T t1 
    LEFT OUTER JOIN 
     T t2 

ON t1.RN1 = t2.RN2 
+0

Funcionaría para SQL Server, pero ahora me doy cuenta de que no está etiquetado. –

Cuestiones relacionadas