Jak uzyskać różnicę między dwoma wierszami dla pola kolumny?

Mam taką tabelę:

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

Wartości wiersza w kolumnie są liczbami całkowitymi, ale nie w sekwencji z tym samym przyrostem. Mogę użyć następującego sql do wyświetlenia wartości przez rowInt:

SELECT * FROM myTable ORDER BY rowInt;

Wyświetli listę wartości według rowInt. Jak można uzyskać różnicę wartości między dwoma wierszami z wynikiem takim jak:

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

Tabela jest w SQL 2005 (Miscrosoft)

Author: David.Chu.ca, 2009-03-11

7 answers

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: myśląc o tym, użycie zapytania podrzędnego w select (odpowiedź Ala Quassnoi) może być bardziej efektywne. Chciałbym wypróbować różne wersje i spojrzeć na plany wykonawcze, aby zobaczyć, które będą działać najlepiej na rozmiar zestawu danych, który masz...

 51
Author: MatBailie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-11 13:58:08
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
 24
Author: Quassnoi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-11 13:50:20

Jeśli naprawdę chcesz być pewien zleceń, użyj "Row_Number ()" i porównaj następny rekord bieżącego rekordu (przyjrzyj się klauzuli "on")

T1.ID + 1 = T2.ID

W zasadzie łączysz następny wiersz z bieżącym wierszem, bez podawania "min" lub "top". Jeśli masz niewielką liczbę rekordów, inne rozwiązania "Dems" lub "Quassanoi" będą działać dobrze.

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
 11
Author: Sung Kim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-12 01:34:26

Obsługa SQL Server 2012 i up LAG / prowadzi Funkcje, Aby uzyskać dostęp do poprzedniego lub następnego wiersza. SQL Server 2005 nie obsługuje tego (w SQL2005 potrzebujesz join lub coś innego).

Przykład SQL 2012 na tych danych

/* Prepare */
select * into #tmp
from
(
    select 2  as rowint,      23 as Value
    union select 3,       45
    union select 17,      10
    union select 9,       0
) x


/* The SQL 2012 query */
select rowInt, Value, LEAD(value) over (order by rowInt) - Value  
from #tmp

LEAD (value) zwróci wartość następnego wiersza w odniesieniu do podanej kolejności w klauzuli "over".

 7
Author: Ansonmus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-07 23:06:37

Czy SQL Server obsługuje funkcje analityczne?

select   rowint,
         value,
         value - lag(value) over (order by rowint) diff
from     myTable
order by rowint
/
 2
Author: David Aldridge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-12 01:39:10
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
 0
Author: mns,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-08 11:40:43

Zapytanie, aby znaleźć różnicę dat między 2 wierszami pojedynczej kolumny

SELECT
Column name,
DATEDIFF(
(SELECT MAX(date) FROM table name WHERE Column name < b. Column name),
Column name) AS days_since_last
FROM table name AS b
 0
Author: arun sivaraman menon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-27 17:26:52