【问题标题】:Aggregate SQL functions with irregular time stamps聚合带有不规则时间戳的 SQL 函数
【发布时间】:2016-01-10 06:53:47
【问题描述】:

我有一张包含时间戳和河流流量的表格。有时我有多个记录,有时我没有记录。

如何计算两个日期之间的平均流量和总流量?

假设两点之间的线性值是可以接受的。也许某种加权平均。如果有一些最小二乘回归算法或类似的东西可以提供更准确的结果,那也很好。

编辑。对于给定的一天,我有以下虚构数据用于说明目的。如果可能的话,我希望做得比假设平均值 146 更好,因为流量在较长时间内很高,而实际平均值可能超过 200。

10/12/15 12:00 AM   100
10/12/15 12:01 AM   102
10/12/15 12:02 AM   104
10/12/15 12:03 AM   106
10/12/15 12:04 AM   200
10/12/15 10:00 PM   204
10/12/15 11:00 PM   208

Average             146

【问题讨论】:

  • 我不太确定我是否理解您的问题。您只是想要加权平均/回归,还是对已有的东西有技术问题?
  • 最小二乘回归算法确定两个变量之间的最佳线性关系,但是您明确不希望“假设两点之间的线性值”。那么你想要什么样的关系呢?还是这个问题?在将离散数据转换为连续关系时,您必须做出一些假设。
  • @JulienBlanchard 如果可能的话,加权平均或回归会很好。
  • @eirikir 不,我说线性值“是”可以接受的。如果在 SQL 中可以使用 LSR,我认为那会更好。只是寻找任何可用的东西(希望快速简单)。
  • 流量使用什么样的值?某种“每秒 x”,您想要时间范围内的总“x”?

标签: mysql sql time-series


【解决方案1】:

您需要进行加权平均。为此,您需要下一个时间戳:

select rf.*,
       (select rf2.timestamp
        from riverflow rf2
        where rf2.timestamp > rf.timestamp
        order by rf.timestamp asc
        limit 1
       ) as nextTimestamp
from riverflow rf;

接下来是加权平均值。我不知道您想如何处理测量周期可能与给定日期不一致的问题。相反,我们将只取值并报告开始和结束观察时间:

select min(timestamp) as start, max(timestamp) as end,
       (sum(riverflow * timestampdiff(second, timestamp, nexttimestamp) / (24*60*60)) /
        (timestampdiff(second, min(timestamp), max(timestamp)) / (24*60*60)
       ) as avgRiverflow
from (select rf.*,
             (select rf2.timestamp
              from riverflow rf2
              where rf2.timestamp > rf.timestamp
              order by rf2.timestamp asc
              limit 1
             ) as nextTimestamp
      from riverflow rf
      where timestamp >= $date1 and timestamp < $date2
     ) t;

【讨论】:

  • 感谢 Gordon,我认为这正是我所希望的。我编辑了我的原始帖子,以显示给定一天大部分时间的高流量场景。它考虑到了,对吧?
  • @user1032531 。 . .这应该将持续时间考虑到加权平均值中。
  • 尚未测试,但认为这是正确的方法。谢谢戈登。 PS。为什么你认为我的问题被否决了?我觉得还不错。
【解决方案2】:

这样的事情通常应该是正确的方向:

SELECT AVG(dayflowRate) AS avgFlowRate, SUM(dayFlow) AS totalFlow
FROM (
SELECT DATE(theTS) AS theDate, AVG(flowRate) AS dayFlowRate
    , AVG(flowRate) * (24*60*60) AS dayFlow
FROM theTable
WHERE theTS BETWEEN [beginTS] AND [endTS]
GROUP BY theDate
) AS dayQ
;

但是,它假设 24 * 60 * 60 乘数为一整天(只是为了清楚起见)。如果您需要更高的精度,则需要查看 MIN 和 MAX 聚合以及 TIME_TO_SEC 函数。

我认为这(下)可能更准确一点:

SELECT AVG(dayflowRate) AS avgFlowRate, SUM(dayFlow) AS totalFlow
FROM (
SELECT DATE(theTS) AS theDate, AVG(flowRate) AS dayFlowRate
    , AVG(flowRate) 
      * ( TIME_TO_SEC(LEAST(MAX(theTS), [endTS]) 
          - TIME_TO_SEC(GREATEST(MIN(theTS), [beginTS]))
        )
      AS dayFlow
FROM theTable
WHERE theTS BETWEEN [beginTS] AND [endTS]
GROUP BY theDate
) AS dayQ
;

编辑:也可能不是,如果当天的测量时间是上午 11 点和下午 1 点,那么即使是在多天的中间,它的 dayFlow 实际上也只会持续两个小时。

这应该是最好的:

SELECT AVG(dayflowRate) AS avgFlowRate, SUM(dayFlow) AS totalFlow
FROM (
SELECT DATE(theTS) AS theDate, AVG(flowRate) AS dayFlowRate
    , AVG(flowRate) 
      * ( IF(DATE(theTS)=DATE([endTS]), TIME_TO_SEC([endTS]), (24*60*60))
          - IF(DATE(theTS)=DATE([beginTS]), TIME_TO_SEC([beginTS]), 0)
        )
      AS dayFlow
FROM theTable
WHERE theTS BETWEEN [beginTS] AND [endTS]
GROUP BY theDate
) AS dayQ
;

【讨论】:

  • 假设我在上午 12 点的读数为 100,在凌晨 1 点读数为 110,在凌晨 2 点读数为 200,在晚上 11 点读数为 210。这表明平均值为 155。然而,实际上平均值可能在 200 左右,因为经历较高流量的持续时间要长得多。
  • 我想到了,但我认为这种想法做出了太多假设,无法通过查询来处理。作为对比,如果流量在上午 6 点为 1000,在晚上 10 点为 100,则假设 16 小时跨度大于另一个将是错误的(在我看来)。
猜你喜欢
  • 1970-01-01
  • 2021-03-17
  • 2015-05-23
  • 1970-01-01
  • 1970-01-01
  • 2011-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多