【问题标题】:Taking a rolling average of three records at a time with two group by values一次取三个记录的滚动平均值,两个 group by 值
【发布时间】:2017-01-25 15:29:57
【问题描述】:

我正在处理的数据没有主键,而是按 TMC 值和日期值分组。我正在尝试做的是取 5 分钟的纪元值,然后将它们组合成一个 15 分钟的纪元,一次平均三个记录。所以 epoch 0, 1, 2 一起平均得到一个新记录,然后是 3,4,5 等等。这是一个示例表。我不知道如何正确格式化:

TMC         DATE    EPOCH   TRAVEL_TIME_ALL_VEHICLES
113N04415   1012016 0       228
113N04415   1012016 1       228
113N04415   1012016 2       222
113N04415   1012016 3       224
113N04415   1012016 4       229
113N04415   1012016 5       223

我认为我对这段代码很接近,因为它适用于第一条记录,但第二条记录失败:

select tmc, date, avg(Travel_TIME_ALL_VEHICLES) AS TRAVEL_avg
from (select I40_2016_ALL.*, 
             row_number() over (order by TMC, date, epoch) as rn 
      from I40_2016_ALL) I40_2016_ALL
where tmc = '113n04415' and date = '1012016'
group by TMC, DATE, floor((rn - 1) / 3)
ORDER BY TMC, DATE

【问题讨论】:

  • 请用您实际使用的 RDBMS 标记您的问题。 MySQL 还没有实现像 row_number afaik 这样的窗口函数。
  • 关系数据库管理系统?我正在使用 microsoft sql server management studio。

标签: sql sql-server grouping average


【解决方案1】:

嗯嗯,没试过,但是怎么样:

    select tmc, date, floor((epoch + 1) / 3) as part, 
           avg(Travel_TIME_ALL_VEHICLES) AS TRAVEL_avg
      from I40_2016_ALL
     where tmc = '113n04415' and date = '1012016'
     group by TMC, DATE, floor((epoch + 1) / 3)

或者如果你想要每一行都有总数...

        select tmc, date, floor((epoch + 1) / 3) as part, 
               avg(Travel_TIME_ALL_VEHICLES) 
                over (partition by TMC, DATE, floor((epoch + 1) / 3)) AS TRAVEL_avg
          from I40_2016_ALL
         where tmc = '113n04415' and date = '1012016'

【讨论】:

  • 这些中没有 FROM 子句。
  • 好多了,但是分段差了一个。前两个记录是自己的,最后一个记录是自己的。我认为这是因为总共有 287 条记录。所以某处只会有 2 条记录被平均。
  • 我通过从 epoch 中删除 +1 来更正您的代码,这又发现了另一个问题。纪元值不一致,因为编号存在间隙。这可以在第 21 部分看到,其中缺少 epoch 64。有没有办法纠正这个问题?
  • 是的,你是对的,“+1”必须去......让我理解,你想按 3 条物理记录组还是按 3 个连续“纪元”组来分组?所以 (0,1,2),(3,4,5),(6,7,8),(9,11),(12,13,14) 即使缺少 10 ?或者 (0,1,2),(3,4,5),(6,7,8),(9,11,12),(13,14) 这将是物理行号?
  • 是的,只要 epoch 不丢失记录,我们就可以进行排序。他们是。因此,某些段的平均时间为 5 分钟或 10 分钟,这是行不通的。所以这个顺序应该是我想要达到的目标:
【解决方案2】:

你可以像这样使用整数除法:

SELECT TMC, [DATE], EPOCH, AVG(TRAVEL_TIME_ALL_VEHICLES) AS TRAVEL_avg       
FROM (
   SELECT TMC, [DATE], TRAVEL_TIME_ALL_VEHICLES,
          ROW_NUMBER() OVER (ORDER BY TMC, [DATE], EPOCH) AS rn
   FROM I40_2016_ALL) AS t
GROUP BY TMC, [DATE], (rn -1)/ 3
ORDER BY TMC, [DATE]

此查询将行 1,2,3 放在一组中,将行 4, 5, 6 放在下一组中,等等。

【讨论】:

  • 这没有做任何事情,只是显示香草记录。
  • @BenZeddicus 道歉。我无意中在GROUP BY 子句中包含了EPOCH 字段。请检查我所做的修改。
  • 这行得通,但订购无处不在。我需要它按 tmc 和日期排序。
  • @BenZeddicus 然后添加一个ORDER BY 子句。
【解决方案3】:

类似:

SELECT AVG(TRAVEL_TIME_ALL_VEHICLES) 
FROM
(
SELECT TRAVEL_TIME_ALL_VEHICLES AS TRAVEL_TIME_ALL_VEHICLES
,(ROW_NUMBER() OVER (Order by EPOCH) + 2)/3 AS GroupID
FROM
YourTable
) AS d
GROUP BY d.GroupID

【讨论】:

  • Msg 207,第 16 级,状态 1,第 6 行列名“RANK”无效。消息 4108,级别 15,状态 1,第 6 行窗口函数只能出现在 SELECT 或 ORDER BY 子句中。
  • 对不起,我删除了 RANK,替换为 EPOCH
  • 仍然有一个错误窗口函数只能出现在select或order by子句中。
  • 你确定吗?我已将其从内部选择中删除
  • Msg 2809, Level 16, State 1, Line 7 对过程“I40_2016_ALL”的请求失败,因为“I40_2016_ALL”是一个表对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-09
  • 1970-01-01
  • 2016-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多