【问题标题】:Show average values for large amount of data显示大量数据的平均值
【发布时间】:2013-10-13 08:27:37
【问题描述】:

我有一个名为 WindData 的 MySQL 数据库,如下所示:

  • 时间戳
  • 温度
  • 风速
  • 风向

我每 2-3 分钟添加一个新行,所以一年多的时间里会有很多行。

现在我想在某个时间范围内(4 天前、上个月、上 6 个月、2011-2012...)将数据显示为图表。假设我想显示过去一年的温度变化情况,使用 Google Charts 来显示。然后谷歌图表对您可以使用的数据点数量有一个最大限制。

然后我想要一个 SQL 查询,在其中我指定给我的时间范围 (2012-01-01 -- 2013-10-10)

  • 固定的行数(例如 200)
  • 每一行都包含该时间间隔内的平均值和最大值。

一个 ascii 艺术示例:

...............1..............2...............+..............199..............200

. 是我表中的一行,数字代表前几个点的平均值和最大值。

一些可能显示我正在尝试完成的伪代码是:

SELECT AVG(temperature) 
FROM WindData 
WHERE timestamp > 2012-01-01 AND timestamp < 2013-10-10

这只会给我一个结果,我得到整个时间范围的平均值。 所以也许有一种方法可以再创建一条 SQL 语句,以不同的时间范围运行上述 sql 语句 200 次。

SELECT AVG(temperature) 
FROM WindData 
WHERE timestamp > 2012-01-01 AND timestamp < 2013-02-1

SELECT AVG(temperature) 
FROM WindData 
WHERE timestamp > 2012-02-01 AND timestamp < 2013-03-1 

SELECT AVG(temperature) 
FROM WindData 
WHERE timestamp > 2012-03-01 AND timestamp < 2013-04-1

SELECT AVG(temperature) 
FROM WindData 
WHERE timestamp > 2012-04-01 AND timestamp < 2013-05-1

...等等。

如果有人有兴趣,我将使用此处的帮助在 www.surfvind.se 上展示更好的图表,该图表显示来自自制气象站的天气数据。

【问题讨论】:

  • 你能告诉我们你到目前为止得到了什么吗?告诉我们您遇到了哪些具体问题。
  • 目前我正在使用不太好的解决方案,即从我的 c# 代码中获取所有行,然后我自己计算所有平均值。 :-) 但显然这不是一个好方法,因为我每次都会从 SQL 服务器下载大量数据。我还尝试运行 200 个具有不同时间范围的 sql 查询,我在其中要求我想要的 AVG 值。但这也不是一个好的做法,但也许这是最好的方法?
  • 更新了描述,以更好地解释我想要完成的任务。
  • 您是否已设法优化您的 SQL 查询?有什么结果可以分享吗? :)

标签: mysql sql average


【解决方案1】:

您可以使用以下方法获得固定数量的行:-

SELECT units.i + tens.i * 10 + hundreds.i AS aNumber
FROM (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) units
CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) tens
CROSS JOIN (SELECT 0 AS i UNION SELECT 1 ) hundreds

您可以使用类似的方法来获取不同的范围,并将其与您的数据结合起来以获取每个范围内的值的数量。

编辑 - 使用您添加的详细信息:-

SELECT Sub1.aDate, AVG(temperature)
FROM 
(
    SELECT DATE_ADD('2012-01-01', INTERVAL units.i + tens.i * 10 + hundreds.i * 100 DAY) AS aDate
    FROM (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) units
    CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) tens
    CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) hundreds
) Sub1
LEFT OUTER JOIN
WindData
ON Sub1.aDate = DATE(WindData.`timestamp`)
GROUP BY Sub1.aDate

这是从 2012-01-01 开始的 1000 天范围(如果需要,您可以轻松地在子选择中限制该范围),并将其与一天的温度值相匹配,并按日期获取平均组.

【讨论】:

  • 我真的不知道这将如何帮助我获得 x 平均值。
  • 您需要生成一系列波段。像上面这样的代码可以给你一个值范围(给你 0 到 199)。通常我会使用类似的东西将开始日期添加为天数。然后将其与您要检查的字段匹配。我会根据您自原始帖子以来添加的详细信息提出一些建议。
  • 这是不正确的。 :) 加载大约 30 秒后,sqlserver 中止查询。而且我不太喜欢这种方法。如果可以的话,更好的方法是:a)计算两个初始日期之间的行数。 b) 将 'a' 的结果除以 200,然后创建一个 for 循环,在 200 个新日期之间运行一个简单的 select avg(temperature)。
  • 循环选择往往非常缓慢。上面的查询应该很快,尽管它必须将时间戳转换为日期和时间是很痛苦的。它可以很容易地修改为提供 200 个日期/时间戳范围,尽管那样你会有一些非常奇怪的开始和结束日期。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-30
  • 1970-01-01
  • 2020-02-20
相关资源
最近更新 更多