我现在正在计划一个SQL语句,需要有人来看看我的想法。
这是我的表:
id stat period
--- ------- --------
1 10 1/1/2008
2 25 2/1/2008
3 5 3/1/2008
4 15 4/1/2008
5 30 5/1/2008
6 9 6/1/2008
7 22 7/1/2008
8 29 8/1/2008
创建表
CREATE TABLE tbstats
(
id INT IDENTITY(1, 1) PRIMARY KEY,
stat INT NOT NULL,
period DATETIME NOT NULL
)
go
INSERT INTO tbstats
(stat,period)
SELECT 10,CONVERT(DATETIME, '20080101')
UNION ALL
SELECT 25,CONVERT(DATETIME, '20080102')
UNION ALL
SELECT 5,CONVERT(DATETIME, '20080103')
UNION ALL
SELECT 15,CONVERT(DATETIME, '20080104')
UNION ALL
SELECT 30,CONVERT(DATETIME, '20080105')
UNION ALL
SELECT 9,CONVERT(DATETIME, '20080106')
UNION ALL
SELECT 22,CONVERT(DATETIME, '20080107')
UNION ALL
SELECT 29,CONVERT(DATETIME, '20080108')
go
我希望计算每个统计信息与下一个统计信息之间的差异,然后计算差距的平均值。'
Thougts:
我需要在其后续行中加入每条记录。我可以使用灵活的连接语法来做到这一点,这要归功于我知道id字段是一个没有间隙的整数序列。
通过对表进行别名,我可以将它合并到SQL查询中两次,然后通过在第一个别名表的id中加1来以交错的方式将它们连接在一起。表中的第一条记录的id为1.1 + 1 = 2,因此它应该连接在第二个别名表中id为2的行上。等等。
现在我只想从另一个中减去一个。
然后我会使用ABS函数来确保我总是得到正整数作为减法的结果,无论表达式的哪一侧是更高的数字。
有没有更简单的方法来实现我的目标?
答案 0 :(得分:2)
lead
分析函数应该可以解决问题:
SELECT period, stat, stat - LEAD(stat) OVER (ORDER BY period) AS gap
FROM tbstats
答案 1 :(得分:1)
间隙的平均值可以通过计算第一个值和最后一个值之间的差值并除以一个元素个数来完成:
select sum(case when seqnum = num then stat else - stat end) / (max(num) - 1);
from (select period, row_number() over (order by period) as seqnum,
count(*) over () as num
from tbstats
) t
where seqnum = num or seqnum = 1;
当然,您也可以使用lead()
进行计算,但这也可以在SQL Server 2005和2008中使用。
答案 2 :(得分:1)
通过使用Join也可以实现此目的
SELECT t1.period,
t1.stat,
t1.stat - t2.stat gap
FROM #tbstats t1
LEFT JOIN #tbstats t2
ON t1.id + 1 = t2.id
答案 3 :(得分:0)
要计算每个统计量与下一个统计量之间的差异,LEAD() and LAG()可能是最简单的选择。您提供一个ORDER BY
,LEAD( something )返回下一个 ,而LAG( something )返回上一个 按给定顺序。
select
x.id thisStatId,
LAG(x.id) OVER (ORDER BY x.id) lastStatId,
x.stat thisStatValue,
LAG(x.stat) OVER (ORDER BY x.id) lastStatValue,
x.stat - LAG(x.stat) OVER (ORDER BY x.id) diff
from tbStats x