【问题标题】:Reporting on a grouped average over a group of records报告一组记录的分组平均值
【发布时间】:2015-12-16 20:24:19
【问题描述】:

我的目标是生成一份报告,显示一周中给定日期和/或一天中某个时间车库的平均占用率(y 轴)。我的数据模型如下:

  • 车库has_many汽车和车库has_many约会,through: :cars
  • 汽车has_many约会
  • 约会具有以下字段:
    • picked_up_at(日期时间)
    • returned_at(日期时间)

此外,Garage 有一个字段 capacity (integer),这是车库中可容纳的最大汽车数量。

如果我有一个过去 6 个月的约会列表,我想生成一个折线图,其中 x 轴显示一周中的每一天,细分为 4 小时间隔,而 y-轴显示给定天/小时间隔的 6 个月期间的平均占用率(车库中的汽车数量/容量),我该如何收集这些数据以进行报告?

例如一辆车从一个约会返回到下一个约会的取车时间为In,从约会的取车时间到returned_at时间为Out

我在将这些数据点连接到有意义地报告并将它们呈现给最终用户的最佳方式时遇到了很多麻烦。

我正在使用 Rails 4.1 和 Ruby 2.0。

编辑:SQL Fiddle - http://sqlfiddle.com/#!9/a72fe/1

【问题讨论】:

  • 你的小提琴是为 MySQL 准备的。您需要将其更改为 Postgres 以匹配您的问题:sqlfiddle.com/#!15/77901/1。此外,您忽略了在 returned_at 中提及可能的 NULL 值(我还调整了架构以匹配您的列名。)
  • 那么你有答案了吗?
  • @ErwinBrandstetter - 很抱歉延迟选择答案,我已经出国了,但我会努力实施您的解决方案,一旦我这样做,我将接受答案。再次感谢

标签: sql ruby-on-rails ruby postgresql activerecord


【解决方案1】:

这个查询可以完成所有事情(适应您添加的小提琴):

SELECT a.ts, g.*, round((a.ct * numeric '100') / g.capacity, 2) AS pct
FROM  (
   SELECT ts, c.garage_id, count(*) AS ct
   FROM   generate_series(timestamp '2015-06-01 00:00'  -- lower and
                        , timestamp '2015-12-01 00:00'  -- upper bound of range
                        , interval  '4h') ts
   JOIN   appointment a ON a.picked_up_at <= ts     -- incl. lower
                       AND (a.returned_at >  ts OR
                            a.returned_at IS NULL)  -- excl. upper bound
   JOIN   car c ON c.id = a.car_id
   GROUP  BY 1, 2
   ) a
JOIN   garage g ON g.id = a.garage_id
ORDER  BY 1, 2;

SQL Fiddle.

如果returned_at IS NULL,此查询假定汽车仍在使用中。所以其他情况不应该出现NULL,否则你在计算中有错误。

首先,我使用方便的generate_series() 函数构建时间序列。

然后加入时间戳在预订中的约会。
我假设每个约会都包含较低和不包含较高时间戳,因为它是普遍的约定。

在我们加入车库之前进行汇总和计数(这样更快)。比较:

外部SELECT中的百分比计算。
我将bigint 数字与numeric(或可选的realfloat)相乘以保留小数位,这将在整数除法中被截断。然后我四舍五入到两位小数。

请注意,这并不完全是每个 4 小时期间的平均百分比,而只是每个时间点的当前百分比,是真实平均值的近似值。您可能会从一个奇怪的时间戳开始,例如“2015-06-01 01:17”,这样就不会陷入可能会在整小时或其他时间翻过的预订之间,这可能会增加近似值的平均误差。

您也可以精确计算 4 小时的周期,但这更复杂。一种简单的技术是将时间间隔减少到 10 分钟,或者以足够详细的粒度来捕捉完整画面。

相关(有一个精确计算的例子):

【讨论】:

  • 感谢您快速详细的回复!我将对此进行审查/测试并报告!
  • 当我将你的查询复制到我的小提琴中时,我收到了这个错误:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'numeric '100') / g.capacity, 2) AS pct FROM ( SELECT ts, c.garage_id, count(' at line 1,这应该像你写的那样直接工作吗?
  • @jackerman09:因为 your 小提琴是用于 MySQL 的(这对于标记为 Postgres 的问题来说是完全错误的)。试试 my 小提琴,它可以工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-17
  • 1970-01-01
  • 1970-01-01
  • 2013-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多