我在SQL Server Express版中有以下表格:
Time Device Value
0:00 1 2
0:01 2 3
0:03 3 5
0:03 1 3
0:13 2 5
0:22 1 7
0:34 3 5
0:35 2 6
0:37 1 5
该表用于记录报告其最新值的不同设备的事件。我想做的是以我通过时间尺度呈现平均数据的方式准备数据,并最终使用这些数据创建图表。我通过以下方式在Excel中操作此示例数据:
Time Average value
0:03 3,666666667
0:13 4,333333333
0:22 5,666666667
0:34 5,666666667
0:35 6
0:37 5,333333333
所以,在时间0:03,我需要获取表格中的最新数据并计算平均值。在这种情况下,它是(3 + 3 + 5)/ 3 = 3,67。在时间0:13,步骤将重复,并再次在0:22,...
因为我想把所有内容保留在SQL表中(我不想用C#或类似的东西创建任何服务来获取数据并将其存储到其他表中)
我想知道以下内容:
提前谢谢你。 标记
与此同时,我有一个想法如何解决这个问题。我很恳请你就此提出意见,我仍然需要一些帮助才能解决问题。 所以,想法是像这样交叉表:
Time Device1Value Device2Value Device3Value
0:00 2 NULL NULL
0:01 NULL 3 NULL
0:03 3 NULL 5
0:13 NULL 5 NULL
0:22 7 NULL NULL
0:34 NULL NULL 5
0:35 NULL 6 NULL
0:37 5 NULL NULL
对此的查询将是:
SELECT Time,
(SELECT Stock FROM dbo.Event WHERE Time = S.Time AND Device = 1) AS Device1Value,
(SELECT Stock FROM dbo.Event WHERE Time = S.Time AND Device = 2) AS Device2Value,
(SELECT Stock FROM dbo.Event WHERE Time = S.Time AND Device = 3) AS Device3Value
FROM dbo.Event S GROUP BY Time
我还需要做的是编写一个用户定义的函数并在此查询中调用它,如果为NULL,则会写入最后一个可用值,如果最后一个可用值不存在,则会留下NULL值。有了这个功能,我会得到以下结果:
Time Device1Value Device2Value Device3Value
0:00 2 NULL NULL
0:01 2 3 NULL
0:03 3 3 5
0:13 3 5 5
0:22 7 5 5
0:34 7 5 5
0:35 7 6 5
0:37 5 6 5
通过得到这个结果,我可以通过仅计算3个相关列并将其除以计数(在本例中为3)来计算每次的平均值。对于NULL,我使用0值。
有人可以建议如何使用最新值替换NULL值来创建用户定义的函数吗?
谢谢马丁。 这个查询有效,但是花了将近21分钟来完成13.576行,这太过分了。
我使用的最终查询是:
SELECT Time,
(SELECT TOP 1 Stock FROM dbo.Event e WHERE e.Time <= S.Time AND Device = 1 ORDER BY e.Time DESC) AS Device1Value,
(SELECT TOP 1 Stock FROM dbo.Event e WHERE e.Time <= S.Time AND Device = 2 ORDER BY e.Time DESC) AS Device2Value,
(SELECT TOP 1 Stock FROM dbo.Event e WHERE e.Time <= S.Time AND Device = 3 ORDER BY e.Time DESC) AS Device3Value
FROM dbo.Event S GROUP BY Time
但我已将它扩展到10台设备。
我同意这不是最好的方法。有没有其他方法可以为平均计算准备数据,因为这只需要太多的处理。
答案 0 :(得分:0)
这是一种方式。它使用“Quirky Update”方法填补空白。这依赖于未记录的行为,因此您可能更喜欢使用游标。
DECLARE @SourceData TABLE([Time] TIME, Device INT, value FLOAT)
INSERT INTO @SourceData
SELECT '0:00',1,2 UNION ALL
SELECT '0:01',2,3 UNION ALL
SELECT '0:03',3,5 UNION ALL
SELECT '0:03',1,3 UNION ALL
SELECT '0:13',2,5 UNION ALL
SELECT '0:22',1,7 UNION ALL
SELECT '0:34',3,5 UNION ALL
SELECT '0:35',2,6 UNION ALL
SELECT '0:37',1,5
CREATE TABLE #tmpResults
(
[Time] Time primary key,
[1] FLOAT,
[2] FLOAT,
[3] FLOAT
)
INSERT INTO #tmpResults
SELECT [Time],[1],[2],[3]
FROM @SourceData
PIVOT ( MAX(value) FOR Device IN ([1],[2],[3])) AS pvt
ORDER BY [Time];
DECLARE @1 FLOAT, @2 FLOAT, @3 FLOAT
UPDATE #tmpResults
SET @1 = [1] = ISNULL([1],@1),
@2 = [2] = ISNULL([2],@2),
@3 = [3] = ISNULL([3],@3)
SELECT [Time],
(SELECT AVG(device)
FROM (SELECT [1] AS device
UNION ALL
SELECT [2]
UNION ALL
SELECT [3]) t) AS [Average value]
FROM #tmpResults
DROP TABLE #tmpResults
答案 1 :(得分:0)
因此,我发现其中一个可能的解决方案效率更高(14.574行不到一秒)。我还没有时间详细审查结果,但第一方面看起来很有希望。这是3设备示例的代码:
选择时间,
SUM(CASE MAC WHEN'1'那么股票0结束)Device1Value,
SUM(CASE MAC WHEN '2'那么股票0结束)Device1Value,
SUM(CASE MAC WHEN'3'那么股票0结束)Device1Value,
来自dbo.Event
GROUP BY时间
按时间顺序
在任何情况下,我都会测试Martin提供的代码,看看它对结果是否有任何影响。