Подтвердить что ты не робот

Как получить разницу между двумя строками для поля столбца?

У меня есть таблица вроде этого:

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)

4b9b3361

Ответ 1

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: Думать об этом, используя подзапрос в select (ala Quassnoi), может быть более эффективным. Я бы изучил разные версии и посмотрел планы выполнения, чтобы посмотреть, какие из них будут лучше всего соответствовать размеру набора данных, который у вас есть...

Ответ 2

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

Ответ 3

Если вы действительно хотите быть уверенными в заказах, используйте "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

Ответ 4

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".

Ответ 5

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

select   rowint,
         value,
         value - lag(value) over (order by rowint) diff
from     myTable
order by rowint
/

Ответ 6

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

Ответ 7

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

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

Ответ 8

Я просто сделал бы небольшую функцию для этого. Вбросьте два значения, вам нужно знать разницу между ними и вычесть меньшее из большего значения. Что-то вроде:

CREATE FUNCTION [dbo].[NumDifference] 
    (   @p1 FLOAT,
        @p2 FLOAT )
RETURNS FLOAT
AS
BEGIN
    DECLARE @Diff FLOAT
    IF @p1 > @p2 SET @Diff = @p1 - @p2 ELSE SET @Diff = @p2 - @p1
    RETURN @Diff
END

В запросе, чтобы получить разницу между столбцами a и b:

SELECT a, b, dbo.NumDifference(a, b) FROM YourTable