Как получить разницу между двумя строками для поля столбца?
У меня есть таблица вроде этого:
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)
Ответы
Ответ 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