显示数据集的平均值,不同 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),因此,我想得到平均值。
例如:
- 天 - Return 所有数据(已经得到这个!)
- 周 - Return 每小时平均值的数据(例如,会有 24 * 1 小时平均值,* 7 天)
- 月 - Return 3 小时平均值的数据(例如 8 * 平均值
超过 3 小时,* 30)
- 每年 - Return 每日平均值中的数据(例如 1 * 平均值
超过 24 小时,* 365)
此处显示了数据集的一个小示例:
+--------------------------------------------------------------------------------+
+ 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_ 等列。
数据库:MS SQL 服务器 11.0.3156.
我有一个 table 用于记录周期性数据值。关键列是: fldObjectGUID(varchar)、fldDataTimestamp(日期时间)、fldConfigItem(varchar)、fldConfigItemValue(数字)
我想检索不同时间范围(日、周、月)的数据。但是为了将 returned 数据品脱的数量保持在可管理的数量(例如少于 < 350),因此,我想得到平均值。
例如:
- 天 - Return 所有数据(已经得到这个!)
- 周 - Return 每小时平均值的数据(例如,会有 24 * 1 小时平均值,* 7 天)
- 月 - Return 3 小时平均值的数据(例如 8 * 平均值 超过 3 小时,* 30)
- 每年 - Return 每日平均值中的数据(例如 1 * 平均值 超过 24 小时,* 365)
此处显示了数据集的一个小示例:
+--------------------------------------------------------------------------------+
+ 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_ 等列。