【问题标题】:postgresql events per hours每小时的 postgresql 事件
【发布时间】:2014-12-30 10:43:48
【问题描述】:

我需要使用不同的分组(人员、事件类型等)计算每个工作时间的事件。

这是我的问题的简化架构。

create table person (
  id        integer PRIMARY KEY,
  name      text
);

create table occupation (
  id        integer PRIMARY KEY,
  name      text,
  start_date    date,
  end_date  date,
  person_id     integer
);

create table work_shift (
  shift     integer PRIMARY KEY,
  start_date    date,
  end_date  date,
  hours     integer,
  occupation_id integer
);

create table event ( 
  id        integer PRIMARY KEY,
  type      text,
  event_date    date,
  person_id     integer
);

样本数据:

insert into person values (1, 'first person');
insert into person values (2, 'second person');

insert into occupation values (1, 'MUSICIAN', to_date('2014-01-01', 'YYYY-MM-DD'), to_date('2014-12-31', 'YYYY-MM-DD'), 1);
insert into occupation values (2, 'MUSICIAN', to_date('2014-01-01', 'YYYY-MM-DD'), to_date('2014-12-31', 'YYYY-MM-DD'), 2);


delete from work_shift;
insert into work_shift values (1, to_date('2014-01-01', 'YYYY-MM-DD'), to_date('2014-01-01', 'YYYY-MM-DD'), 7, 1);
insert into work_shift values (2, to_date('2014-01-02', 'YYYY-MM-DD'), to_date('2014-01-02', 'YYYY-MM-DD'), 8, 1);
insert into work_shift values (3, to_date('2014-01-01', 'YYYY-MM-DD'), to_date('2014-01-01', 'YYYY-MM-DD'), 8, 2);
insert into work_shift values (4, to_date('2014-01-02', 'YYYY-MM-DD'), to_date('2014-01-02', 'YYYY-MM-DD'), 7, 2);

-- person 1, playing, day 1
insert into event values (1, 'PLAYING', to_date('2014-01-01', 'YYYY-MM-DD'), 1);
insert into event values (2, 'PLAYING', to_date('2014-01-01', 'YYYY-MM-DD'), 1);
insert into event values (3, 'PLAYING', to_date('2014-01-01', 'YYYY-MM-DD'), 1);
insert into event values (4, 'PLAYING', to_date('2014-01-01', 'YYYY-MM-DD'), 1);
insert into event values (5, 'PLAYING', to_date('2014-01-01', 'YYYY-MM-DD'), 1);

-- person 1, singing, day 1
insert into event values (6, 'SINGING', to_date('2014-01-01', 'YYYY-MM-DD'), 1);
insert into event values (7, 'SINGING', to_date('2014-01-01', 'YYYY-MM-DD'), 1);

-- person 1, playing, day 2
insert into event values (8, 'PLAYING', to_date('2014-01-02', 'YYYY-MM-DD'), 1);
insert into event values (9, 'PLAYING', to_date('2014-01-02', 'YYYY-MM-DD'), 1);
insert into event values (10, 'PLAYING', to_date('2014-01-02', 'YYYY-MM-DD'), 1);
insert into event values (11, 'PLAYING', to_date('2014-01-02', 'YYYY-MM-DD'), 1);

-- person 2, playing, day 1
insert into event values (12, 'PLAYING', to_date('2014-01-01', 'YYYY-MM-DD'), 2);
insert into event values (13, 'PLAYING', to_date('2014-01-01', 'YYYY-MM-DD'), 2);
insert into event values (14, 'PLAYING', to_date('2014-01-01', 'YYYY-MM-DD'), 2);

-- person 2, singing, day 1
insert into event values (15, 'SINGING', to_date('2014-01-01', 'YYYY-MM-DD'), 2);
insert into event values (16, 'SINGING', to_date('2014-01-01', 'YYYY-MM-DD'), 2);
insert into event values (17, 'SINGING', to_date('2014-01-01', 'YYYY-MM-DD'), 2);

-- person 2, singing, day 2
insert into event values (18, 'SINGING', to_date('2014-01-02', 'YYYY-MM-DD'), 2);
insert into event values (19, 'SINGING', to_date('2014-01-02', 'YYYY-MM-DD'), 2);
insert into event values (20, 'SINGING', to_date('2014-01-02', 'YYYY-MM-DD'), 2);

例如,我将如何计算每天每小时的事件?我遇到的问题是我的计算多次计算相同的工作班次。所以我得到了多次计算 id 1 的工作班次。

按职业和月份分组时想要的结果是

occupation    day   ratio
MUSICIAN      1     0,93    ((3+2+2+2+5) / (7+8))
MUSICIAN      1     0,73    ((4+7) / (7+8))

我需要计算的其他示例是每人每天的小时数。

我的基本查询目前是

SELECT 
  month,
  some-group-by-term,
  some-aggregate-function
FROM table
GROUP BY group-by-term

是否可以创建类似于计算这些事件/小时(按某个术语分组)的查询?

【问题讨论】:

  • 你的数据库设计很差。你应该先解决这个问题。 +1 用于提供数据和所需的输出。
  • 感谢您的评论。为了在我的真实数据库中澄清,我有引用人员的事件表。我也有单独的表上的工作班次,参考人。显示的表格结构只是为了演示问题区域。
  • 将 1xn 关系加入 1xm 关系会导致 nxm 关系,这可能是您面临的问题。您需要显示一个简化但兼容的模式,以便可以指出解决方案。您可能需要预先聚合引用表。
  • 我添加了一个更好的表和数据表示(仍然简化)作为示例。

标签: sql postgresql


【解决方案1】:

我应该在这些情况下使用双重分组:

select occupation, day, sum(events)*1.0/sum(hours) ratio  from 
(select occupation,day,work_shift_id, sum(events) events
from person_work 
group by occupation, day, work_shift_id) a
join
person_work_shift b on a.work_shift_id=b.shift_id
group by occupation, day

【讨论】:

  • 这似乎为示例数据提供了正确的结果。如果我仍然发现一些奇怪的东西,我需要检查我的真实数据。
  • 这解决了我的计算问题。虽然我不得不为它制作一些令人讨厌的原生查询。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-12
  • 2020-05-05
  • 1970-01-01
  • 2012-08-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多