将时间聚合数据分解为几个均匀分布的间隔

发布于 2025-01-16 23:54:02 字数 1385 浏览 0 评论 0原文

数据库结构如下所示。 它只是代表员工、正在处理的任务数量、开始整个活动的事实以及结束的事实和所花费的秒数的总摘要的一行。

员工number_of_tasksstart_actend_acttotal_seconds
AXF-6263512:3014:106000

我想将其按相等的时间间隔分解,每次 1 小时,另外总结总秒数,落入特定的时间间隔。从而得到这样的结果。那么有没有什么SQL方法可以解决这个问题呢?

员工number_of_tasksstart_actend_actTotal_seconds
AXF-6263512:0013:001800
AXF-6263513:0014:003600
AXF-6263514:0015:00600

提前感谢您提供任何帮助!

The database structure looks like this.
It's just a single row representing employee, number of tasks were being processed, the fact of starting whole activity and also the fact of ending and total summary of spent seconds.

employeenumber_of_tasksstart_actend_acttotal_seconds
AXF-6263512:3014:106000

I want to break this down on equal intervals for 1 hour each, additionally summing up total seconds, falling into particular interval. Thus getting a reslut like this. So is there any kind of SQL approach to implement this problem ?

employeenumber_of_tasksstart_actend_acttotal_seconds
AXF-6263512:0013:001800
AXF-6263513:0014:003600
AXF-6263514:0015:00600

Thanks in advance for any kind of help !

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

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

发布评论

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

评论(2

吻安 2025-01-23 23:54:02

有趣的任务,我决定加入一个系列,然后找出他的重叠部分。

我的方法是采用灵活的时间单位,这样您就可以更改为天/周/等

with employees AS (
  SELECT
    'AXF-6263' AS employee,
    5 AS number_of_tasks,
    '2022-03-25 12:30'::timestamp AS start_act,
    '2022-03-25 14:10'::timestamp AS end_act,
    6000 AS total_seconds
),

-- select a set of employees to work on
sample_set AS (
  SELECT
    employee,
    start_act,
    end_act
  FROM
    employees
  -- WHERE ...
  -- LIMIT ...
),

-- choose a unit for the interval
unit AS (
  SELECT
    'hour' AS unit,
    '1 hour'::interval AS interval
),

-- generate a full series of time intervals
time_spans AS (
  SELECT
    sample_set.employee,
    generate_series(
       min(date_trunc(unit.unit, start_act)),
       max(date_trunc(unit.unit, end_act)),
       unit.interval
     ) AS start_act
  FROM
    sample_set
  JOIN unit
    ON true
  GROUP BY
    employee,
    unit.interval
)

-- final results
SELECT
  employee,
  number_of_tasks,
  time_spans.start_act,
  time_spans.start_act + unit.interval AS end_act,
  CASE
    WHEN employees.start_act > time_spans.start_act THEN time_spans.start_act - employees.start_act + unit.interval
    WHEN employees.end_act < time_spans.start_act + unit.interval THEN employees.end_act - time_spans.start_act
    ELSE unit.interval
  END AS total_seconds
FROM
  employees
JOIN time_spans USING (employee)
JOIN unit ON
  true
ORDER BY
  employee,
  time_spans.start_act

Interesting task, I decided to join on a series then figure out he overlap.

My approach here, with a flexible time unit so you could change to days/weeks/etc

with employees AS (
  SELECT
    'AXF-6263' AS employee,
    5 AS number_of_tasks,
    '2022-03-25 12:30'::timestamp AS start_act,
    '2022-03-25 14:10'::timestamp AS end_act,
    6000 AS total_seconds
),

-- select a set of employees to work on
sample_set AS (
  SELECT
    employee,
    start_act,
    end_act
  FROM
    employees
  -- WHERE ...
  -- LIMIT ...
),

-- choose a unit for the interval
unit AS (
  SELECT
    'hour' AS unit,
    '1 hour'::interval AS interval
),

-- generate a full series of time intervals
time_spans AS (
  SELECT
    sample_set.employee,
    generate_series(
       min(date_trunc(unit.unit, start_act)),
       max(date_trunc(unit.unit, end_act)),
       unit.interval
     ) AS start_act
  FROM
    sample_set
  JOIN unit
    ON true
  GROUP BY
    employee,
    unit.interval
)

-- final results
SELECT
  employee,
  number_of_tasks,
  time_spans.start_act,
  time_spans.start_act + unit.interval AS end_act,
  CASE
    WHEN employees.start_act > time_spans.start_act THEN time_spans.start_act - employees.start_act + unit.interval
    WHEN employees.end_act < time_spans.start_act + unit.interval THEN employees.end_act - time_spans.start_act
    ELSE unit.interval
  END AS total_seconds
FROM
  employees
JOIN time_spans USING (employee)
JOIN unit ON
  true
ORDER BY
  employee,
  time_spans.start_act
夜声 2025-01-23 23:54:02

使用generate_series并将其与您的表交叉连接。

-- Test case
create temporary table the_table (employee text, number_of_tasks integer, start_act time, end_act time, total_seconds integer);
insert into the_table values ('AXF-6263', 5, '12:30', '14:10', 6000);

-- Query
select employee, number_of_tasks, 
       h::time start_act, h::time  + interval '1 hour' end_act, 
       extract('epoch' from least(h::time + interval '1 hour', end_act) - greatest(h::time, start_act))::integer total_seconds
from the_table cross join lateral
     generate_series(date_trunc('hour', current_date + start_act), date_trunc('hour', current_date + end_act), interval '1 hour') h
order by h;
员工任务数开始时间结束时间总秒数
AXF-6263512:00:0013:00:001800
AXF-6263513:00:0014:00:003600
AXF-6263514:00:0015:00:00600

Use generate_series and cross join it with your table.

-- Test case
create temporary table the_table (employee text, number_of_tasks integer, start_act time, end_act time, total_seconds integer);
insert into the_table values ('AXF-6263', 5, '12:30', '14:10', 6000);

-- Query
select employee, number_of_tasks, 
       h::time start_act, h::time  + interval '1 hour' end_act, 
       extract('epoch' from least(h::time + interval '1 hour', end_act) - greatest(h::time, start_act))::integer total_seconds
from the_table cross join lateral
     generate_series(date_trunc('hour', current_date + start_act), date_trunc('hour', current_date + end_act), interval '1 hour') h
order by h;
employeenumber_of_tasksstart_actend_acttotal_seconds
AXF-6263512:00:0013:00:001800
AXF-6263513:00:0014:00:003600
AXF-6263514:00:0015:00:00600
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文