【发布时间】:2016-06-12 20:41:27
【问题描述】:
我正在尝试实现一个计算存储活动开始和结束时间的空闲时间的函数。我在 PostgreSQL 9.5.3 上实现了我的数据库。这是活动表的样子
activity_id | user_id | activity_title | starts_at | ends_at
(serial) | (integer) | (text) | (timestamp without time zone) |(timestamp without time zone)
---------------------------------------------------------------------------------------------------------------------------
1 | 1 | Go to school | 2016-06-12 08:00:00 | 2016-06-12 14:00:00
2 | 1 | Visit my uncle | 2016-06-12 16:00:00 | 2016-06-12 17:30:00
3 | 1 | Go shopping | 2016-06-12 18:00:00 | 2016-06-12 21:15:00
4 | 1 | Go to Library | 2016-06-13 10:00:00 | 2016-06-13 12:00:00
5 | 1 | Install some programs on my laptop | 2016-06-13 18:00:00 | 2016-06-13 19:00:00
我的真实表的实际表定义:
CREATE TABLE public.activity (
activity_id serial,
user_id integer NOT NULL,
activity_title text,
starts_at timestamp without time zone NOT NULL,
start_tz text NOT NULL,
ends_at timestamp without time zone NOT NULL,
end_tz text NOT NULL,
recurrence text NOT NULL DEFAULT 'none'::text,
lat numeric NOT NULL,
lon numeric NOT NULL,
CONSTRAINT pk_activity PRIMARY KEY (activity_id),
CONSTRAINT fk_user_id FOREIGN KEY (user_id)
REFERENCES public.users (user_id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
我想使用以(user_id INTEGER, range_start TIMESTAMP, range_end TIMESTAMP) 作为参数的 PL/pgSQL 函数计算该用户每天的空闲时间。我想要这条 SQL 语句的输出:
SELECT * from calculate_spare_time(1, '2016-06-12', '2016-06-13');
变成这样:
spare_time_id | user_id | starts_at | ends_at
(serial) | (integer) | (timestamp without time zone) |(timestamp without time zone)
----------------------------------------------------------------------------------------
1 | 1 | 2016-06-12 00:00:00 | 2016-06-12 08:00:00
2 | 1 | 2016-06-12 12:00:00 | 2016-06-12 16:00:00
3 | 1 | 2016-06-12 17:30:00 | 2016-06-12 18:00:00
4 | 1 | 2016-06-12 21:15:00 | 2016-06-13 00:00:00
5 | 1 | 2016-06-13 00:00:00 | 2016-06-13 10:00:00
6 | 1 | 2016-06-13 12:00:00 | 2016-06-13 18:00:00
7 | 1 | 2016-06-13 19:00:00 | 2016-06-14 00:00:00
我的想法是从同一日期发生的下一个活动的开始时间中减去一个活动的结束时间,但我坚持使用 PL/pgSQL 实现这一点,尤其是关于如何处理同一时间。
【问题讨论】:
-
希望这次编辑能明确我的问题。
-
现在好多了。数据有什么限制吗?活动的时间范围可以重叠吗?它们可以相邻吗?列可以为 NULL 吗?
starts_at和ends_at是 inclusive 还是 exclusive 界限? (下限包含,上限不包含,将是规范默认值。)允许的时间戳是否有 15 分钟的网格?实际完整的表定义(具有所有约束的CREATE TABLE脚本)将阐明所有这些。该功能很大程度上取决于必须预期的数据。 -
我在帖子中添加了
CREATE TABLE脚本。仅当活动发生在lat和lon列表示的同一位置时,活动的时间范围才能重叠。starts_at是包含绑定,而ends_at是独占绑定。 -
我不明白允许的时间戳上的 15 分钟网格是什么。我不明白这一点。
-
“15 分钟网格”表示以 15 分钟为间隔输入时间值,这将允许离散解。我添加了一个通用解决方案。
标签: postgresql function range plpgsql gaps-and-islands