sql查询获取表中多次出现的每个行项的2个最近行之间的差异

时间:2017-10-18 15:26:41

标签: sql-server

Sql查询,它获取表中多次出现的每个值的2个最近行之间的差异。 例如

book  value         date
A   4   2017-07-17 09:16:44.480 
A   2   2017-08-15 10:05:58.273
B   3   2017-04-15 10:05:58.273
C   2   2017-08-15 10:05:58.273
B   3   2017-04-13 10:05:58.273
B   3   2017-04-12 10:05:58.273

应该返回

A 2
B 0

4 个答案:

答案 0 :(得分:0)

这是一个解决方案:

SELECT book, MAX(value) - MIN(value) AS difference FROM (
    SELECT book, value, ROW_NUMBER() OVER (PARTITION BY book ORDER BY date DESC) AS rownum FROM t
) AS a WHERE rownum <= 2 GROUP BY book HAVING MAX(rownum) >= 2

这里是SQLFiddle

答案 1 :(得分:0)

SELECT id_pk FROM [table] GROUP BY [fields you whant to compare by] HAVING COUNT(*) > 1)

此选择将返回已重新元素的pk列表

因此,在其他选择中,您将获得另一个选择

Select * from [table] where id_pk in(
SELECT id_pk FROM [table] GROUP BY [fields you whant to compare by] HAVING COUNT(*) > 1)) limit 2

这是功能性的,仍然不好,因为我没有分析复杂性。

答案 2 :(得分:0)

我会使用分析函数:

;with CTE as (
    SELECT book
        ,value
        ,LAG(value) OVER (PARTITION BY book ORDER BY date) last_value
        ,ROW_NUMBER() OVER (PARTITION BY book ORDER BY date DESC) rn
    FROM MyTable
)
SELECT book
    ,value - last_value as value_change
FROM CTE
WHERE rn = 1
    AND last_value IS NOT NULL
SQL Server 2012中添加了

LAG(),但即使您使用的是更高版本,您的数据库也必须将兼容版本设置为110或更高才能使其可用。这是一个适用于SQL Server 2005或更高版本,或数据库兼容性为90或更高版本的替代方案。

;with CTE as (
    SELECT book
        ,value
        ,ROW_NUMBER() OVER (PARTITION BY book ORDER BY date DESC) rn
    FROM MyTable
)
SELECT c1.book
    c1.value - c2.value as value_change
FROM CTE c1
INNER JOIN CTE c2
    ON c1.book = c2.book
WHERE c1.rn = 1
    AND c2.rn = 2

答案 3 :(得分:0)

在计算之前添加一个rownumber:

create table #test ([book] char(1), [value] int, [date] datetime)

insert into #test values ('A', 4, '2017-07-17 09:16:44.480') 
insert into #test values ('A', 2, '2017-08-15 10:05:58.273')
insert into #test values ('B', 3, '2017-04-15 10:05:58.273')
insert into #test values ('C', 2, '2017-08-15 10:05:58.273')
insert into #test values ('B', 3, '2017-04-13 10:05:58.273')
insert into #test values ('B', 3, '2017-04-12 10:05:58.273')

;with cte as(
Select ROW_NUMBER () OVER (order by [book], [date] ) as rownumber, *
from #test)
select distinct [1].book, abs(first_value([1].[Value]) over (partition by [1].book order by [1].rownumber desc) - [2].val2) as [Difference]
from cte [1]
inner join
(select rownumber, book, first_value([Value]) over (partition by book order by rownumber desc) as val2
from cte) [2] on [1].book = [2].book and [1].rownumber < [2].rownumber