我的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,然后在它们之间做出差异,并将结果保存到一个将被添加的变量中。表的结尾使用相同的逻辑,但我认为可以通过一个查询和更好的性能来完成它。你可以帮我解决这个问题吗?
答案 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;