【发布时间】:2021-04-17 13:15:03
【问题描述】:
我正在编写一个 psql 过程来读取源表,然后聚合并写入聚合表。 我的表源包含 2 列 beg,end 是指客户端连接到网站,客户端断开连接。 我想为每个客户计算他花费的时间。使用生成系列的目的是当事件超过一天时。
我的伪代码如下
execute $$SELECT MAX(date_) FROM $$||aggregate_table INTO max_date;
IF max_date is not NULL THEN
execute $$DELETE FROM $$||aggregate_table||$$ WHERE date_ >= $$||quote_literal(max_date);
ELSE
max_date := 'XXXXXXX';
end if;
SELECT * from (
select
Id, gs.due_date,
(case
When TRIM(set) ~ '^OPT[0-9]{3}/MINUTE/$'
Then 'minute'
When TRIM(set) ~ '^OPT[0-9]{3}/SECOND/$'
Then 'second'
as TIME,
sum(extract(epoch from (least(s.end, gs.date_ + interval '1 day') -
greatest(s.beg, gs.date_)
)
) / 60) as Timing
from source s cross join lateral
generate_series(date_trunc(‘day’, s.beg), date_trunc('day',
least(s.end,
CASE WHEN $$||quote_literal(max_date)||$$ = ‘XXXXXXX’
THEN (current_date)
ELSE $$||quote_literal(max_date)||$$
END)
), interval '1 day’) gs(date_)
where ( (beg, end) overlaps ($$||quote_literal(max_date)||$$'00:00:00', $$||quote_literal(max_date)||$$'23:59:59’))
group by id, gs.date_, TIME
) as X
where ($$||quote_literal(max_date)||$$ = X.date_ and $$||quote_literal(max_date)||$$ != ‘XXXXXXX’)
OR ($$||quote_literal(max_date)||$$ ='XXXXXXX')
表源数据
number, beg, end, id, set
(10, '2019-10-25 13:00:00', '2019-10-25 13:30:00', 1234, 'OPT111/MINUTE/'),
(11, '2019-10-25 13:00:00', '2019-10-25 14:00:00', 1234, 'OPT111/MINUTE/'),
(12, '2019-11-04 09:19:00', '2019-11-04 09:29:00', 1124, 'OPT111/SECOND/'),
(13, '2019-11-04 22:00:00', '2019-11-05 02:00:00', 1124, 'OPT111/MINUTE/')
Expected_output 聚合表
2019-10-25, 1234, MINUTE, 90(1h30)
2019-11-04, 1124, SECOND, 10
2019-11-04, 1124, MINUTE, 120
2019-11-05, 1124, MINUTE, 120
我的代码的问题是,如果我有明天将添加的新行,例如 (14, '2019-11-06 12:00:00', '2019-11- 06 13:00:00',1124,'OPT111/MINUTE/')。
请哪位大神帮忙?
谢谢
【问题讨论】:
-
对不起它的 psql @jarlh 它的我。
-
请解释逻辑。真的不清楚你要做什么。
-
@GordonLinoff 谢谢我添加描述。如果还不清楚,请告诉我。丹克
-
@GordonLinoff 我清楚了吗?如果不告诉我,请告诉我
-
将跨越午夜的每条记录拆分为两条记录(一条记录直到午夜,另一条记录在午夜之后)为
UNIONCTE,然后进行聚合。
标签: sql postgresql plpgsql dynamic-sql