Как получить разницу между двумя строками для поля столбца? - PullRequest
52 голосов
/ 11 марта 2009

У меня есть такая таблица:

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

Значения столбца rowInt являются целыми, но не в последовательности с одинаковым приращением. Я могу использовать следующий sql для вывода значений по rowInt:

SELECT * FROM myTable ORDER BY rowInt;

Это будет список значений по rowInt. Как можно получить разницу значений между двумя строками с таким результатом:

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

Таблица в SQL 2005 (Miscrosoft)

Ответы [ 7 ]

54 голосов
/ 11 марта 2009
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)

РЕДАКТИРОВАТЬ: Думая об этом, использование подзапроса в select (ответ аля Quassnoi) может быть более эффективным. Я бы попробовал разные версии и посмотрел планы выполнения, чтобы выяснить, какие из них лучше всего подходят для размера имеющегося у вас набора данных ...

25 голосов
/ 11 марта 2009
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
11 голосов
/ 12 марта 2009

Если вы действительно хотите быть уверены в заказах, используйте «Row_Number ()» и сравните следующую запись текущей записи (внимательно посмотрите на предложение «on»)

T1.ID + 1 = T2.ID

Вы в основном присоединяетесь к следующей строке с текущей строкой, не указывая "min" или не делая "top". Если у вас есть небольшое количество записей, другие решения от "Dems" или "Quassanoi" будут работать нормально.

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
9 голосов
/ 04 октября 2016

SQL Server 2012 и выше поддержка LAG / LEAD функции для доступа к предыдущей или последующей строке. SQL Server 2005 не поддерживает это (в SQL2005 требуется соединение или что-то еще).

Пример SQL 2012 для этих данных

/* 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 (значение) будет возвращать значение следующей строки по отношению к заданному порядку в предложении «over».

2 голосов
/ 12 марта 2009

Поддерживает ли SQL Server аналитические функции?

select   rowint,
         value,
         value - lag(value) over (order by rowint) diff
from     myTable
order by rowint
/
0 голосов
/ 27 мая 2016

Запрос на поиск разницы дат между 2 строками одного столбца

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 голосов
/ 23 ноября 2009
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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...