我有一个由时间戳值和绝对(米)值组成的数据集。有时仪表值重置为零,这意味着我必须迭代并逐个计算增量,然后将其累加以获得给定周期的总和。计算连续行之间的delta值的有效方法?
例如:
Timestamp Value
2009-01-01 100
2009-01-02 105
2009-01-03 120
2009-01-04 0
2009-01-05 9
这里总为29,计算公式为:
(105 - 100) + (120 - 105) + (0) + (9 - 0) = 29
我使用MS-SQL服务器对于这一点,并开放给任何建议。
现在,我使用的是光标要做到这一点,它会检查增量不为负,然后合计起来:
DECLARE CURSOR curTest CURSOR FAST_FORWARD FOR
SELECT value FROM table ORDER BY timestamp
OPEN curTest
DECLARE @delta bigint, @current bigint, @last bigint
SET @delta = 0
FETCH curTest INTO @current
WHILE @@FETCH_STATUS = 0
BEGIN
IF (@current IS NOT NULL) AND (@current > 0)
BEGIN
IF (@last IS NOT NULL) AND (@current > @last)
SET @delta = @delta + (@current - @last)
SET @last = @current
FETCH curTest INTO @current
END
END
CLOSE curTest
DEALLOCATE curTest
这将是很好得到一个数据集的像:
Timestamp Value LastValue
2009-01-01 100 NULL
2009-01-02 105 100
2009-01-03 120 105
2009-01-04 0 120
2009-01-05 9 0
因为这将很容易抓住变化,为(Value> LastValue)过滤,并做一个SUM()。
我想:
SELECT m1.timestamp, m1.value,
(SELECT TOP 1 m2.value FROM table WHERE m2.timestamp < m1.timestamp ORDER BY m2.timestamp DESC) as LastValue
FROM table
但其实这原来是比光标较慢:当我一起在SQL工作室与“节目的执行计划”中运行这些,这样做的相对成本100% (使用7或8次操作 - 时间戳中聚簇索引扫描的大多数),并且游标为0%(有3次操作)。 (我在这里没有简单展示的是我有几个不同的数字集合,在这个表格中还有一个外键 - 所以总是有一个WHERE子句限制到一个特定的集合。有几个地方我一次计算给定时间段内的这些总数,因此它变成了相当的性能瓶颈,非游标方法也可以很容易地修改为GROUP BY键,并一次返回所有集合 - 但是在我的测试中,这实际上比运行光标多次要慢,因为除了整体速度较慢外,还有额外的GROUP BY和SUM()操作开销。)
1为ROW_NUMBER的使用来计算() – 2009-08-13 04:19:45