计算查询中值的差值的总和

时间:2018-01-26 11:48:45

标签: sql sql-server count

我的SQL查询有问题,我必须计算时间段内每个“范围”值的值之间的差异。这是我想要做的一个例子:

我有一个包含两个列数据和一个时间戳

的表
Value   Time
5       16:00
6       17:00
7       18:00
0       19:00
1       20:00
2       21:00
3       22:00
4       23:00
5       00:00
6       01:00
0       02:00
...

我必须给出每个时隙上值的差值之和。因此,这个表格将给出结果8,因为你有7和5以及6和0之间的差异。

我有想法通过分析每一行来计算这些价值差异的总和,然后改变找到的最小值和最大值,直到我达到0,然后在它们之间做出差异,并将结果保存到一个将被添加的变量中。表的结尾使用相同的逻辑,但我认为可以通过一个查询和更好的性能来完成它。你可以帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

这在黑暗中非常刺激,然而,它带有警告。您需要在数据中使用某种标识列。目前,我们无法按照您在示例数据中提供的顺序订购数据。

SQL Server表中的数据存储为HEAP。它有 NO 顺序。当您运行SELECT * FROM [Table];时,数据将以任何顺序从服务器返回,并且#34;感觉就像#34;。它可能是你插入的顺序(如果它是一个小桌子),但是,它永远不会得到保证。它也可能是你CLUSTERED INDEX的顺序,然而,它再也不能保证。当您拥有更大的表并且多个核心用于运行相同的查询时,这变得尤为常见。

根据您的数据,订购对您的问题的答案至关重要。如果我们无法通过使用该数据来实现您的示例数据中的订单,那么您的目标是无法实现的。

因此,为此,我有 来向表中添加其他列。这可能意味着您无法回复此日期,因为我们可以保证IDENTITY列以正确的顺序填充。

无论如何,进入解决方案。这只是一个想法,依赖于您使用SQL Server 2012以及(我正在谈论的IDENTITY列)。但是,如果你不能改变桌子的DDL,那么你就无法实现目标;简单地说。

USE Sandbox;
GO

CREATE TABLE #Test (ID int IDENTITY(1,1), --Note I have had to add an IDENTITY Column
                                          --Without this, your goal is not possible, as 
                                          --your ordering cannot be maintained.
                    [Value] int, [Time] time);

INSERT INTO #Test ([Value], [Time])
VALUES (5,'16:00'),
       (6,'17:00'),
       (7,'18:00'),
       (0,'19:00'),
       (1,'20:00'),
       (2,'21:00'),
       (3,'22:00'),
       (4,'23:00'),
       (5,'00:00'),
       (6,'01:00'),
       (0,'02:00');

WITH Groups AS(
    SELECT *,
           COUNT(CASE [Value] WHEN 0 THEN 0 END) OVER (ORDER BY ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Grp
    FROM #Test),
FirstLast AS(
    SELECT FIRST_VALUE([Value]) OVER (PARTITION BY Grp ORDER BY ID) AS FirstValue,
           LAST_VALUE([Value]) OVER (PARTITION BY Grp ORDER BY ID ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS LastValue,
           ROW_NUMBER() OVER (PARTITION BY Grp ORDER BY ID) AS RN
    FROM Groups)
SELECT SUM(LastValue - FirstValue) AS TotalDifference
FROM FirstLast
WHERE RN = 1;

DROP TABLE #Test;