使用Generate Series生成用于预约的时隙

时间:2018-10-22 07:24:23

标签: postgresql postgresql-9.2 generate-series

我正在尝试生成可用的时隙功能。 我每天都在记录开始时间和结束时间。

for eg: start time is 08:00 AM and end time is 03:00 PM.

我还有另一个表可以记录当天的休息时间,

for eg: 11:00 AM to 11:15 AM and 01:00 PM to 1:30 PM.

在另一个桌子上,我存储着已经预订的空位

for eg: 
09:00 AM to 09:30 AM
11:15 AM to 11:45 AM
01:30 PM 02:00PM

我正在使用generate_series生成开始时间和结束时间之间的时间间隔。

select * FROM generate_series(
       timestamp '2016-11-09 08:00 AM',
       timestamp '2016-11-09 03:00 PM',
       INTERVAL '30m'
    ) t

我需要从这个生成的系列中排除休息时间和已经预订的时间。我尝试使用除功能以外的功能,但是无法删除此插槽(上午11:15至11:45)。 我通常如何编写条件以删除此条件?

除查询

SELECT t
    FROM generate_series(
       timestamp  '2016-11-09 08:00 AM',
       timestamp  '2016-11-09 03:00 PM',
       INTERVAL '1 hour'
    ) t
    EXCEPT
    SELECT concat(start_date,' ' , start_time)::timestamp as booked 
    FROM my_table where start_date::date = '2016-11-09';

my_table详细信息

CREATE TABLE public.my_table
(
id bigint NOT NULL,
start_date character varying(500),
start_time character varying(500),
CONSTRAINT pk_my_table PRIMARY KEY (id))
WITH (
OIDS=FALSE
);

1 个答案:

答案 0 :(得分:0)

以下工作方式,建议您使用较小的时间间隔,大概15分钟:

with my_table as (
    select '09:00 AM' start_time , '2016-11-09'::character varying start_date
    )

SELECT *
    FROM generate_series(
       timestamp  '2016-11-09 08:00 AM',
       timestamp  '2016-11-09 03:00 PM',
       INTERVAL '15 minutes'
    ) t
EXCEPT
SELECT concat(start_date,' ' , start_time)::timestamp as booked 
FROM my_table where start_date::date = '2016-11-09'

但是说实话,我只是不会将约会存储为看起来像日期的字符串或看起来像一天中的时间的字符串。字符(500)列会很乐意接受'this is not a date or a time'之类的数据,突然之间您会遇到一个错误,因为它不会转换。或30/02/2019之类的日期可能存在于数据中,很难找到。

为什么不只将约会开始存储为时间戳?这样会更加高效。例如

with my_table as (
    select '2016-11-09 09:00:00'::timestamp start_date
    )


SELECT *
    FROM generate_series(
       timestamp  '2016-11-09 08:00 AM',
       timestamp  '2016-11-09 03:00 PM',
       INTERVAL '15 minutes'
    ) t
EXCEPT
SELECT start_date
FROM my_table 
where start_date >= '2016-11-09' and start_date < '2016-11-10'

这样的查询将利用该start_date列上的索引来过滤数据。

请不要使用字符串存储日期或时间。我也不会将日期与一天中的时间分开。