我有以下(简化的)PostgreSQL数据库表,其中包含有关在某个设备上完成维护的信息:
id bigint NOT NULL,
"time" timestamp(0) with time zone,
action_name text NOT NULL,
action_info text NOT NULL DEFAULT ''::text,
action_name字段可以有四个感兴趣的值:
MAINTENANCE_START
DEVICE_DEFECT
DEVICE_REPAIRED
MAINTENANCE_STOP
<other (irrelevant) values>
我必须使用此表中的信息进行BIRT报告。每次遇到MAINTENANCE_STOP操作时,我都应该在表中有一个条目。如果在此MAINTENANCE_STOP操作与其相应的MAINTENANCE_START操作之间(应该是MAINTENANCE_START操作且最大“time”值小于MAINTENANCE_STOP操作的那个)我遇到DEVICE_DEFECT或DEVICE_REPAIRED操作我应该在表格单元格中写入字符串“Device”不可用“,否则我应该写”设备可用“。
另外,我应该将维护的持续时间计算为MAINTENANCE_STOP操作和MAINTENANCE_START操作之间的时差。
我首先尝试在SQL查询中执行此操作,但现在我不确定它是否可行。你推荐什么方法?
答案 0 :(得分:1)
我的工作片段:
CREATE TABLE "log"
(
id bigint NOT NULL,
time timestamp(0) with time zone,
action_name text NOT NULL,
action_info text NOT NULL DEFAULT ''::text
);
insert into log(id,time,action_name,action_info) values ( 1, '2011-01-01', 'MAINTENANCE_START', 'maintenance01start');
insert into log(id,time,action_name,action_info) values ( 2, '2011-02-01', 'MAINTENANCE_START', 'maintenance02start');
insert into log(id,time,action_name,action_info) values ( 3, '2011-03-01', 'MAINTENANCE_START', 'maintenance03start');
insert into log(id,time,action_name,action_info) values ( 4, '2011-04-01', 'MAINTENANCE_START', 'maintenance04start');
insert into log(id,time,action_name,action_info) values ( 5, '2011-01-10', 'MAINTENANCE_STOP', 'maintenance01stop');
insert into log(id,time,action_name,action_info) values ( 6, '2011-02-10', 'MAINTENANCE_STOP', 'maintenance02stop');
insert into log(id,time,action_name,action_info) values ( 7, '2011-03-10', 'MAINTENANCE_STOP', 'maintenance03stop');
--insert into log(id,time,action_name,action_info) values ( 8, '2011-04-10', 'MAINTENANCE_STOP', 'maintenance04stop');
insert into log(id,time,action_name,action_info) values ( 9, '2011-02-05', 'DEVICE_DEFECT', 'maintenance02defect');
insert into log(id,time,action_name,action_info) values ( 10, '2011-03-05', 'DEVICE_REPAIRED', 'maintenance03repaired');
select
maintenance.start as start
, maintenance.stop as stop
, count (device_action.*) as device_actions
from (select
l_start.time as start
, (select time
from log l_stop
where l_stop.time > l_start.time
and l_stop.action_name = 'MAINTENANCE_STOP'
order by time asc limit 1) as stop
from log l_start
where l_start.action_name='MAINTENANCE_START' order by l_start.time asc) maintenance
left join log device_action
on device_action.time > maintenance.start
and device_action.time < maintenance.stop
and device_action.action_name like 'DEVICE_%'
group by maintenance.start
, maintenance.stop
order by maintenance.start asc
;
小心表现。如果Postgres没有优化嵌套查询,则需要O(n ^ 2)时间。
如果你可以:
time
视为主键(隐含索引)time
列上创建索引。