显示数据集的平均值,不同 date/time 范围

Show averages of a dataset, different date/time ranges

数据库:MS SQL 服务器 11.0.3156.

我有一个 table 用于记录周期性数据值。关键列是: fldObjectGUID(varchar)、fldDataTimestamp(日期时间)、fldConfigItem(varchar)、fldConfigItemValue(数字)

我想检索不同时间范围(日、周、月)的数据。但是为了将 returned 数据品脱的数量保持在可管理的数量(例如少于 < 350),因此,我想得到平均值。

例如:

此处显示了数据集的一个小示例:

    +--------------------------------------------------------------------------------+
+ fldObjectGUID | fldRecordUpdatedTimestamp | fldConfigItem     | fldConfigItemValue |
+ 40010000      | 2015-06-16 18:20:48.000   | ICMPResponseTime  |   4.00             |
+ 40010000      | 2015-06-16 19:22:00.000   | ICMPResponseTime  |   15.00            |
+ 40010000      | 2015-06-16 20:22:14.000   | ICMPResponseTime  |   4.00             |
+ 40010000      | 2015-06-17 17:35:19.000   | ICMPResponseTime  |   6.00             |
+ 40010000      | 2015-06-17 18:36:26.000   | ICMPResponseTime  |   4.00             |
+ 40010000      | 2015-06-28 02:18:31.000   | ICMPResponseTime  |   19.00            |
+ 40010000      | 2015-06-28 03:18:54.000   | ICMPResponseTime  |   9.00             |
+ 40010000      | 2015-06-02 17:25:16.000   | ICMPResponseTime  |   3.00             |
+------------------------------------------------------------------------------------+

以不同的速率为 object (fldObjectGUID) 添加数据。这可能是每 5 分钟一行或每小时一行。数据中可能存在差距(数小时甚至数天)。我想绘制不同时间范围内每个 object 的 fldConfigItemValue 数据图;日(过去 24 小时)、周、月和年。 returned 数据的周期不需要精确。因此,一个月可能只是过去 30 天,或者只是从今天开始的 1 个日历月。

SQL 只需要 return 单个 fldObjectGUID 和 fldConfigItem 组合的数据 - 然后我将修改 run-time 处的 SQL 以获取数据所需的 object/configitem.

数据中可能存在差距,因此没有给定时间段内的数据点。因此,return 值可以为零。

我正在使用 Classic ASP 检索数据,创建 SQL 语句并解析结果。我可以在 ASP 代码中以编程方式实现结果。因此,对于 'Week' 所需的集合,我可以重复调用数据库,使用 AVERAGE 函数和 WHERE 子句来检索记录的子集(从现在到现在 - 1 小时)。存储该值,然后使用 WHERE 子句重复 (NOW - 1 hour to NOW - 2 Hours)。回到过去,直到我获得一周的所有值。 'Month' 和 'Yearly' 例程是相同的,只是 WHERE 子句中的不同时间范围。

然而,即使对我来说,这似乎是一种笨拙的方法,只有一个 SQL 例程(或周、月和年的不同 SQL 例程)必须更快并且/或更优雅。

目前,我有一些 SQL(来自 Whosebug?)我认为可能有用,我让我的代码为 'Month' 视图构建 SQL,就像这样(为了使示例更清晰,我在示例中 hard-coded fldObjectGUID 和 fldConfigItem):

SELECT      top 30 convert(date, l.fldDataTimestamp) as 'fldDataTimestamp_result', l.fldConfigItemValue, l.fldConfigItemValue
FROM        tblObjectHealthCheckData_Historic l
            INNER JOIN  (
            SELECT    MIN(fldDataTimestamp) first_timestamp
            FROM     tblObjectHealthCheckData_Historic
            where fldObjectGUID = '10050400' and fldConfigItem = 'AvailableRAM'
            group by Convert(Date, fldDataTimestamp)
            ) sub_l ON (sub_l.first_timestamp = l.fldDataTimestamp)
where fldObjectGUID = '10050400' and l.fldConfigItem = 'AvailableRAM'
order by fldDataTimestamp desc  

但这只是每天的第一个数据点(正如你所猜到的,虽然我理解 SQL 和编程,但它们只是一种爱好,不是我谋生的东西)所以我正在努力修复此代码。

我假设人们同意,在代码中执行此操作比进行许多单独的 SQL 调用更有效 - 但有人可以帮忙吗?

我会尝试使用 DATEPART 函数,这样您可以获得 fldRecordUpdatedTimestamp 的不同部分,然后是 AVG 字段 fldConfigItemValue。

这会下降到时间戳的单个小时(可能是分钟,请在 T-SQL 中查看 MSDN 中的 DATEPART),因此如果您希望获得每周的每日平均值,那么您需要包括:

day_fldRecordUpdatedTimestamp
week_fldRecordUpdatedTimestamp

这将是每周内每一天的平均值。

下面的示例显示了每月的平均值 - 注意年份,如果您有超过一年的数据,请确保包括 year_fldRecordUpdatedTimestamp 等。

WITH PartsTable As 
(
    SELECT
        fldObjectGUID
        , fldRecordUpdatedTimestamp
        , fldConfigItem
        , fldConfigItemValue
        , DATEPART(HOUR, fldRecordUpdatedTimestamp) As hour_fldRecordUpdatedTimestamp
        , DATEPART(DAY, fldRecordUpdatedTimestamp) As day_fldRecordUpdatedTimestamp
        , DATEPART(WEEK, fldRecordUpdatedTimestamp) As week_fldRecordUpdatedTimestamp
        , DATEPART(MONTH, fldRecordUpdatedTimestamp) As month_fldRecordUpdatedTimestamp
        , DATEPART(YEAR, fldRecordUpdatedTimestamp) As year_fldRecordUpdatedTimestamp
    FROM
        YourLogTable
    --WHERE
    -- Perhaps set a limit here to not get a huge set in the first step.    
)
SELECT
    COUNT(1) As setcount /* Shows how many rows are in each AVG calculation. */
    , fldObjectGUID
    , fldConfigItem
    , month_fldRecordUpdatedTimestamp /* Change this column for specific span you're intrested in. */
    , AVG(fldConfigItemValue) As avg_fldConfigItemValue
FROM
    PartsTable
GROUP BY
    fldObjectGUID
    , fldConfigItem
    , month_fldRecordUpdatedTimestamp /* Change this column for specific span you're intrested in. */
;

最后一点:确保在 SELECT 和 GROUP BY 中包含 month_、week_ 等列。