通过时间尺度(SQL Server)进行平均计算 - 准备图表

时间:2010-12-31 11:34:04

标签: sql-server charts

我在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#或类似的东西创建任何服务来获取数据并将其存储到其他表中)

我想知道以下内容:

  1. 这是正确的方法,还是应该使用其他一些计算图表数据准备平均值的概念?
  2. 如果是,实施它的最佳方法是什么?表视图,数据库中的函数,存储过程(可以从图表API中调用)?
  3. 有关如何实施此建议的任何建议?
  4. 提前谢谢你。 标记

    更新1

    与此同时,我有一个想法如何解决这个问题。我很恳请你就此提出意见,我仍然需要一些帮助才能解决问题。 所以,想法是像这样交叉表:

    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值来创建用户定义的函数吗?

    更新2

    谢谢马丁。 这个查询有效,但是花了将近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台设备。

    我同意这不是最好的方法。有没有其他方法可以为平均计算准备数据,因为这只需要太多的处理。

2 个答案:

答案 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提供的代码,看看它对结果是否有任何影响。