如何避免在PostgreSQL中发现重叠时间戳时插入

如何避免在PostgreSQL中发现重叠时间戳时插入,postgresql,Postgresql,我想检查根据客户的时间戳call_start和call_end是否不相同,以便没有客户同时接听两个电话 我在这里插入了一些客户id for rec in (select t.agent_id, t.call_start, t.call_end, t.aht, t.customer_id from temp_sdg_calls t) loop insert into aa_dev.sdg_calls values(rec.agent_id, rec.call_start, rec.

我想检查根据客户的时间戳call_start和call_end是否不相同,以便没有客户同时接听两个电话

我在这里插入了一些客户id

for rec in (select t.agent_id, t.call_start, t.call_end, t.aht, t.customer_id from temp_sdg_calls t) loop
    insert into aa_dev.sdg_calls
    values(rec.agent_id, rec.call_start, rec.call_end, rec.aht, (select customer_id from aa_dev.sdg_calls order by random() limit 1));
end loop;
我只想在没有类似时间的客户呼叫时从aa_dev.sdg_呼叫中插入customerid,例如,我不需要下面这样的场景。所以为了避免这种情况,我想在插入时检查它,如果出现这种情况,那么选择另一个customerid并在这里插入它

叫你开始 通话结束 客户识别码 2020-11-16 09:12:40 2020-11-16 09:13:05 2345 2020-11-16 09:12:50 2020-11-16 09:13:10 2345
首先选择最佳数据类型:当您有开始和结束时间戳时,它看起来像一个范围。PostgreSQL确实提供了这种数据类型,时间戳范围,tsrange

每个范围都有一个下限和一个上限,即起点和终点。然后还有包含边界和排除边界,表示为[和]的包含边界和(和)的排除边界

大多数情况下,我使用函数来创建范围,在本例中是函数tsrange():

SELECT tsrange('2021-01-20 10:00', '2021-01-20 11:00', '[)');
结果是:

[2021-01-20 10:00:002021-01-20 11:00:00)

这意味着开始于2021-01-20 10:00:00,结束于2021-01-20 11:00:00,但不包括2021-01-20 11:00:00。所以基本上2021-01-20 11:00:00减去1微秒

使用此数据类型,您还可以选择创建,以避免重叠范围。这是使用btree_gist扩展:

CREATE EXTENSION btree_gist;

CREATE TABLE sdg_calls (
  customer_id int4 NOT NULL,
  ts_call tsrange NOT NULL,

    CONSTRAINT unique_customer_call EXCLUDE USING gist (customer_id public.gist_int4_ops WITH pg_catalog.=, ts_call pg_catalog.range_ops WITH pg_catalog.&&)
)
;

INSERT INTO sdg_calls(customer_id, ts_call) VALUES(1, tsrange('2021-02-01 10:00', '2021-02-01 10:15','[)'));
INSERT INTO sdg_calls(customer_id, ts_call) VALUES(1, tsrange('2021-02-01 10:15', '2021-02-01 10:30','[)'));
下一个将失败:

INSERT INTO sdg_calls(customer_id, ts_call) VALUES(1, tsrange('2021-02-01 10:25', '2021-02-01 10:45','[)')); 

现在,您的日常工作中有许多和运算符。这在使用计划软件、预订等时尤其方便。

首先选择最佳数据类型:当您有开始和结束时间戳时,它看起来像一个范围。PostgreSQL确实提供了这个数据类型,时间戳范围,tsrange

每个范围都有一个下界和一个上界,即开始和结束。然后还有包含和排除边界,用[和]表示包含边界,用(和)表示排除边界

大多数情况下,我使用函数来创建范围,在本例中是函数tsrange():

SELECT tsrange('2021-01-20 10:00', '2021-01-20 11:00', '[)');
结果是:

[2021-01-20 10:00:002021-01-20 11:00:00)

这意味着开始于2021-01-20 10:00:00,结束于2021-01-20 11:00:00,但不包括2021-01-20 11:00:00。所以基本上2021-01-20 11:00:00减去1微秒

使用此数据类型,您还可以选择创建,以避免重叠范围。这是使用btree_gist扩展:

CREATE EXTENSION btree_gist;

CREATE TABLE sdg_calls (
  customer_id int4 NOT NULL,
  ts_call tsrange NOT NULL,

    CONSTRAINT unique_customer_call EXCLUDE USING gist (customer_id public.gist_int4_ops WITH pg_catalog.=, ts_call pg_catalog.range_ops WITH pg_catalog.&&)
)
;

INSERT INTO sdg_calls(customer_id, ts_call) VALUES(1, tsrange('2021-02-01 10:00', '2021-02-01 10:15','[)'));
INSERT INTO sdg_calls(customer_id, ts_call) VALUES(1, tsrange('2021-02-01 10:15', '2021-02-01 10:30','[)'));
下一个将失败:

INSERT INTO sdg_calls(customer_id, ts_call) VALUES(1, tsrange('2021-02-01 10:25', '2021-02-01 10:45','[)')); 

现在,您的日常工作中有许多和操作员。这在使用规划软件、预订等时特别方便。

与问题无关,但为什么逐行插入速度慢且效率低?为什么不使用
insert-into-insert-into-aa_-dev.sdg_调用(…)选择…from temp_sdg_calls
?@a_horse_with_no_name因为我想逐行插入,每一行都应该有不同的id。与问题无关,但为什么逐行插入速度慢且效率低?为什么不使用
插入插入aa_dev.sdg_调用(…)选择…从临时sdg呼叫中
?@a_horse_和_no_name_因为我想逐行插入,每一行都应该有不同的id。你能给出一个描述性的答案吗?@Chloe:见上文你能给出一个描述性的答案吗?@Chloe:见上文