按 60 分钟滑动窗口分组

发布于 2024-11-30 21:09:33 字数 1181 浏览 1 评论 0原文

我有一个表,其中包含有关作业的信息:作业类型、开始时间和结束时间。

我想要一份报告,显示每小时运行了多少个作业 - 但不是时钟时间,而是从该组中第一个作业的时间起 60 分钟的偏移时间(它们是一批作业,所以我确定工作类型不会在时间上重叠)。

像这样的事情:

num_of_jobs | job_type | hour
-----------------------------
1254        | B        | 2011-08-22 13:47
9983        | B        | 2011-08-22 14:47
9072        | B        | 2011-08-22 15:47
20309       | B        | TOTAL
79          | C        | 2011-08-22 16:02
105         | C        | 2011-08-22 17:02
184         | C        | TOTAL
10234       | D        | 2011-08-22 17:29
9882        | D        | 2011-08-22 18:29
20116       | D        | TOTAL

如果可以按小时分组(例如 12:00、13:00、14:00),我可以像这样轻松地完成此操作(实际查询的非常简化的版本):

select count(job_id) number_of_jobs, job_type,
    case when to_char(end_date,'YYYY-MM-DD HH24') is not null
         then to_char(end_date,'YYYY-MM-DD HH24')||':00'
         else 'TOTAL'
    end Date_and_hour
from my_jobs
where end_date is not null
group by rollup (to_char(end_date,'YYYY-MM-DD HH24')) , job_type
order by to_char(end_date,'YYYY-MM-DD HH24') asc, job_type asc;

除了按小时分组之外,而不是基于 job_type 的批次中的最小开始时间。

我真的不太确定如何让它发挥作用。

(使用Oracle 10g)

I have a table with information about jobs in it: the job type, the start time, and the end time.

I would like a report that shows me how many jobs ran in each hour - but not clock-hours but 60 minute off-set hours from the time of the first job in that group (they are batches of jobs, so I know for certain that the job-types won't overlap in time).

Something like this:

num_of_jobs | job_type | hour
-----------------------------
1254        | B        | 2011-08-22 13:47
9983        | B        | 2011-08-22 14:47
9072        | B        | 2011-08-22 15:47
20309       | B        | TOTAL
79          | C        | 2011-08-22 16:02
105         | C        | 2011-08-22 17:02
184         | C        | TOTAL
10234       | D        | 2011-08-22 17:29
9882        | D        | 2011-08-22 18:29
20116       | D        | TOTAL

If it was OK to group by Hours (such as 12:00, 13:00, 14:00) I can do this easily enough like this (very simplified version of actual query):

select count(job_id) number_of_jobs, job_type,
    case when to_char(end_date,'YYYY-MM-DD HH24') is not null
         then to_char(end_date,'YYYY-MM-DD HH24')||':00'
         else 'TOTAL'
    end Date_and_hour
from my_jobs
where end_date is not null
group by rollup (to_char(end_date,'YYYY-MM-DD HH24')) , job_type
order by to_char(end_date,'YYYY-MM-DD HH24') asc, job_type asc;

Except it groups on the Hours, not on the smallest start time in a batch based on job_type.

I'm really not quite sure how to get this working.

(using Oracle 10g)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

请帮我爱他 2024-12-07 21:09:33

在我看来,真正的问题是找到每一行属于哪个小时组。一旦获得,您可以将其插入您提供的查询中以获得最终答案。要获取小时组,我们所要做的就是计算出自该组中最早的时间以来已经过去了多少小时:

select floor((end_date - min(end_date) 
                         over (partition by job_type))*24)+1 as hour_group
from my_jobs
where end_date is not null

我使用 trunc 因为我们只关心整个小时并添加一个小时这样我们就从一开始计数,而不是从零开始。由于此解决方案使用分析函数,因此您需要在分组之前将其放入子查询中。


稍微玩了一下,我最终得到以下(未经测试的)查询:

SELECT   COUNT(job_id) number_of_jobs, 
         job_type, 
         min_time + FLOOR((end_date - min_time) * 24) / 24 AS date_and_hour
FROM     (SELECT job_id, 
                 job_type, 
                 end_date, 
                 MIN(end_date) OVER (PARTITION BY job_type) AS min_time
          FROM   my_jobs
          WHERE  end_date IS NOT NULL)
GROUP BY ROLLUP(min_time + FLOOR((end_date - min_time) * 24) / 24), job_type
ORDER BY hour_group ASC, job_type ASC;

原理与我最初的答案相同,我只是稍微移动了数学。

It seems to me that the real issue is in finding which hour-group each row belongs to. Once you have that, you can plug it into the query you provided to get your final answer. To get the hour-group, all we have to do is figure out how many hours have elapse since the earliest time in the group:

select floor((end_date - min(end_date) 
                         over (partition by job_type))*24)+1 as hour_group
from my_jobs
where end_date is not null

I'm using trunc because we only care about whole hours and adding one so that we start counting at one, rather than zero. Since this solution uses analytic functions, you'll need to put it in a subquery before grouping.


Playing with it a little, I get the following (untested) query in the end:

SELECT   COUNT(job_id) number_of_jobs, 
         job_type, 
         min_time + FLOOR((end_date - min_time) * 24) / 24 AS date_and_hour
FROM     (SELECT job_id, 
                 job_type, 
                 end_date, 
                 MIN(end_date) OVER (PARTITION BY job_type) AS min_time
          FROM   my_jobs
          WHERE  end_date IS NOT NULL)
GROUP BY ROLLUP(min_time + FLOOR((end_date - min_time) * 24) / 24), job_type
ORDER BY hour_group ASC, job_type ASC;

The principle is the same as my initial answer, I just moved the math around a little.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文