views:

2491

answers:

5

I have a table like this:

rowInt  Value
2       23
3       45
17      10
9       0
....

The column rowInt values are integer but not in a sequence with same increament. I can use the following sql to list values by rowInt:

SELECT * FROM myTable ORDER BY rowInt;

This will list values by rowInt. How can get get the difference of Value between two rows with the result like this:

rowInt   Value Diff
2        23    22    --45-23
3        45    -35   --10-45
9        0     -45   --0-45
17       10    10    -- 10-0
....

The table is in SQL 2005 (Miscrosoft)

+2  A: 
SELECT rowInt, Value,
       COALESCE(
       (
       SELECT TOP 1 Value
       FROM myTable mi
       WHERE mi.rowInt > m.rowInt
       ORDER BY
             rowInt
       ), 0) - Value AS diff
FROM  myTable m
ORDER BY
      rowInt
Quassnoi
ORDER BY in the inner query should be on rowInt, not Value...
Dems
+3  A: 
SELECT
   [current].rowInt,
   [current].Value,
   ISNULL([next].Value, 0) - [current].Value
FROM
   sourceTable       AS [current]
LEFT JOIN
   sourceTable       AS [next]
      ON [next].rowInt = (SELECT MIN(rowInt) FROM sourceTable WHERE rowInt > [current].rowInt)

EDIT: Thinking about it, using a subquery in the select (ala Quassnoi's answer) may be more efficient. I would trial different versions, and look at the execution plans to see which would perform best on the size of data set that you have...

Dems
If he has an index on rowInt (which I think he does) then my query is more efficient. If he doesn't, then your one is (if it's possible to talk about efficiency in this case). Look here for details: http://stackoverflow.com/questions/590079/for-autoincrement-fields-maxid-vs-top-1-id-order-by-id-desc
Quassnoi
I created a dummy table with 1 million randomly created records and found that both queries took the same time. In fact the only difference in execution plans was the position of a SORT function (I sorted the final output)
Dems
I like your method. It works fine with my case.
David.Chu.ca
Could you mark the answer as accepted? *grin* I'm a kudos whore *giggle*
Dems
A: 

If you really want to be sure of orders, use "Row_Number()" and compare next record of current record (take a close look at "on" clause)

T1.ID + 1 = T2.ID

You are basically joining next row with current row, without specifying "min" or doing "top". If you have a small number of records, other solutions by "Dems" or "Quassanoi" will work fine.

with T2 as (
    select ID = ROW_NUMBER() over (order by rowInt),
      rowInt, Value
    from myTable
)
select  T1.RowInt, T1.Value, Diff = IsNull(T2.Value, 0) - T1.Value
from    ( SELECT ID = ROW_NUMBER() over (order by rowInt), *
      FROM myTable ) T1
     left join T2 on T1.ID + 1 = T2.ID
ORDER BY T1.ID
Sung Meister
A: 

Does SQL Server support analytic functions?

select   rowint,
         value,
         value - lag(value) over (order by rowint) diff
from     myTable
order by rowint
/
David Aldridge
Msg 195, Level 15, State 10, Line 3'lag' is not a recognized built-in function name.
Sung Meister
A: 

select t1.rowInt,t1.Value,t2.Value-t1.Value as diff from (select * from myTable )as t1,

(select * from myTable where rowInt!=1 union all select top 1 rowInt=COUNT(*)+1,Value=0

from myTable)as t2 where t1.rowInt=t2.rowInt-1

mns