【问题标题】:Group by hour, aggregate average按小时分组,合计平均值
【发布时间】:2017-11-03 02:13:03
【问题描述】:

我有一个包含作业历史的 PostgreSQL 表:

CREATE TABLE jobHistory
(
   jobid int4,
   starttime timestamptz,
   endtime timestamptz
);

我正在尝试创建一个 SQL 查询来显示每小时运行的作业的平均数量。应该有 24 行(0-23 表示 24 小时),以包含该小时运行的平均作业数。

jobHistory 表中的总行数约为 20k。这是一个示例:

jobid  startTime                 endTime
------------------------------------------------------
377    2017-11-02 15:43:43.0     2017-11-02 15:49:22.0
114    2017-11-02 15:47:05.0     2017-11-02 15:56:19.0
378    2017-11-02 15:49:22.0     2017-11-02 15:53:01.0
379    2017-11-02 15:53:01.0     2017-11-02 16:33:16.0
380    2017-11-02 16:33:16.0     2017-11-02 16:51:26.0
381    2017-11-02 16:51:26.0     2017-11-02 17:03:00.0
382    2017-11-02 17:03:00.0     2017-11-02 17:11:59.0
383    2017-11-02 17:11:59.0     2017-11-02 17:12:44.0
384    2017-11-02 17:12:43.0     2017-11-02 17:13:36.0
385    2017-11-02 17:13:36.0     2017-11-02 17:14:20.0
386    2017-11-02 17:14:20.0     2017-11-02 17:15:08.0
387    2017-11-02 17:15:08.0     2017-11-02 17:16:03.0
388    2017-11-02 17:16:03.0     2017-11-02 18:31:01.0
150    2017-11-02 17:55:00.0     2017-11-02 18:16:32.0
153    2017-11-02 17:55:00.0     2017-11-02 18:15:28.0
135    2017-11-02 17:55:00.0     2017-11-02 17:55:01.0
132    2017-11-02 17:55:00.0     2017-11-02 18:13:00.0
156    2017-11-02 17:55:00.0     2017-11-02 17:55:06.0
147    2017-11-02 17:55:00.0     2017-11-02 17:57:47.0
138    2017-11-02 17:55:00.0     2017-11-02 18:12:33.0
140    2017-11-02 17:55:00.0     2017-11-02 17:55:17.0
389    2017-11-02 18:31:01.0     2017-11-02 18:38:11.0
390    2017-11-02 18:38:11.0     2017-11-02 18:38:35.0
391    2017-11-02 18:38:35.0     2017-11-02 18:38:39.0

我正在寻找平均每小时的工作数量。作业每天 24 小时不间断运行。有些时间运行的作业比其他时间多。总共有大约120个工作岗位。有些需要几分钟,有些需要几个小时。为了保持负载平衡,当我安排一个新作业时,我想看看哪个小时的平均作业数最少。

【问题讨论】:

  • 需要考虑start time还是end time?因为在某些情况下它们是不同的。 average number of jobs running for that hour 是什么意思?不应该是total number of jobs running for that hour吗?如果不是,你对average jobs 的逻辑是什么?

标签: sql postgresql group-by aggregate


【解决方案1】:

你的问题不清楚。

我假设您正在根据starttime 列查找total number of running jobs per hour,所以下面是查询。

SELECT count(jobid) AS TotalJobs,
       date_trunc('hour', starttime) AS Date_Hour
FROM jobHistory
GROUP BY date_trunc('hour', starttime)
order by Date_Hour;

如果在endTime的基础上需要,可以将上面的查询替换为starttimeendTime

结果:

totaljobs   date_hour
-------------------------------
4           02.11.2017 15:00:00
2           02.11.2017 16:00:00
15          02.11.2017 17:00:00
3           02.11.2017 18:00:00

希望这会有所帮助

DEMO

【讨论】:

  • 这是很棒的 zarruq,但是您的 SQL 正在为每天的每个小时生成一行。我正在寻找的结果在输出中只有 12 行,一天中的每个小时都有 1 行。第一列是小时 (0-23),结果中的第二列是该小时内运行的平均作业数。这意味着需要考虑开始时间和结束时间来确定作业是否在每个小时内“运行”。 “平均”作业数将是运行的作业总数除以源集中每小时的总行数。
  • @aswift:您的查询仍然不清楚。请根据示例数据将所需的输出结果添加到您的问题或评论中。谢谢!
【解决方案2】:

感谢所有查看此内容的人。我相信有一种方法可以使用纯 SQL 获得答案,但我就是想不通。为了回答我的问题,我编写了一个 perl 脚本来获取结果。

这是它的工作原理。

1.) 获取最早的工作记录和最新的工作记录之间的天数,这将用于平均每个小时 0-23 出现的工作数量。
2.) 对于每个作业记录,为作业运行的一天中的每个小时增加一个计数器。例如,如果作业从下午 2 点到下午 6 点运行,则脚本将为 2、3、4、5 和 6 小时增加一个计数器。如果工作超过 23 小时,我将 0-23 的值增加一次。此时,我有一个包含 2 列的结果。第一列是小时 (0-23),第二列是在该小时内运行的作业的出现次数。
3.) 然后,我的脚本会从上面第 2 步中获取数字,然后将其除以天数以得出平均值。

因为我已经编写了一个 perl 脚本来生成结果,所以我现在知道安排新作业的最佳时间段是上午 11 点。

如果有人对处理 SQL 感兴趣,我很想看看它是如何完成的。现在,我将把我的 perl 脚本放在手边。

这里是完整工作历史数据的链接:

https://www.dropbox.com/s/bi66s0thh4sfp46/JobHistoryData.csv?dl=0

这是计算每小时运行作业的平均数量的 perl 脚本的输出:

0 = 2.49
1 = 2.10
2 = 2.16
3 = 2.02
4 = 4.10
5 = 2.86
6 = 2.00
7 = 1.69
8 = 1.69
9 = 1.80
10 = 1.67
11 = 1.53
12 = 1.76
13 = 1.73
14 = 8.33
15 = 2.24
16 = 1.63
17 = 8.67
18 = 6.12
19 = 5.00
20 = 4.84
21 = 3.76
22 = 10.43
23 = 4.37

【讨论】:

    猜你喜欢
    • 2021-12-11
    • 2021-07-07
    • 2020-04-20
    • 2017-02-18
    相关资源
    最近更新 更多