我有一个用户可用性表。每行都有一个start time
和end time
作为时间戳。
当我插入新行时,我检查该行是否与该用户的另一个可用性行重叠,如果确实存在,则更新现有行,如果没有,则添加新行。
问题是当新的可用性与两个现有行重叠时。
例如
'2018-09-01 10:00:00' - '2018-09-01 13:00:00',
'2018-09-01 14:00:00' - '2018-09-01 16:00:00'
并且用户想要添加:
'2018-09-01 11:00:00' - '2018-09-01 17:00:00'.
在这种情况下,第一行将被更新,但第二行将保留在那里。
如何删除/合并所有重叠的行?
我正在使用PostgreSQL
我的SQL
do $$
begin
/* Overlapps availabilty */
IF EXISTS (
SELECT *
FROM availabilities
WHERE ('${startTime}', '${endTime}') OVERLAPS (availabilities.startTime, availabilities.endTime)
AND availabilities.therapist = ${therapist}
) THEN
UPDATE availabilities
SET startTime = LEAST(availabilities.startTime, '${startTime}'::timestamp), endTime = GREATEST(availabilities.endTime, '${endTime}'::timestamp)
WHERE therapist = ${therapist}
AND ('${startTime}', '${endTime}') OVERLAPS (availabilities.startTime, availabilities.endTime);
/* New availabilty */
ELSE
INSERT INTO availabilities
(therapist, startTime, endTime)
VALUES (${therapist}, '${startTime}', '${endTime}');
END IF;
end
$$
更新
我与Michel Milezzi合作,但之前也添加了INSERT。
答案 0 :(得分:1)
已编辑
为了获得所有重叠行的最短开始时间和最长结束时间,您可以将DELETE
与RETURNING
和INSERT
混合使用:
WITH overlapping AS (
DELETE FROM
availabilities
WHERE
(starttime, endtime) OVERLAPS ('2018-09-01 11:00:00','2018-09-01 17:00:00')
AND therapist = 1
RETURNING
therapist,
starttime,
endtime
)
INSERT INTO
availabilities (therapist, starttime, endtime)
SELECT
therapist,
least(min(starttime), '2018-09-01 11:00:00'),
greatest(max(endtime),'2018-09-01 17:00:00')
FROM
overlapping
GROUP BY
therapist;
上一个答案:
我不确定我是否理解正确,但是看来您已经很接近答案了:
--sample
CREATE TABLE availabilities (therapist, starttime, endtime) AS
VALUES
(1, '2018-09-01 10:00:00'::TIMESTAMP, '2018-09-01 13:00:00'::TIMESTAMP),
(1, '2018-09-01 14:00:00', '2018-09-01 16:00:00'),
(1, '2018-10-01 14:00:00', '2018-10-01 16:00:00'),
(2, '2018-09-01 14:00:00', '2018-09-01 16:00:00');
--remove overlapping availabilities
DELETE FROM
availabilities
WHERE
(starttime, endtime) OVERLAPS ('2018-09-01 11:00:00','2018-09-01 17:00:00')
AND therapist = 1;
--insert new availability
INSERT INTO
availabilities (therapist, starttime, endtime)
VALUES
(1, '2018-09-01 11:00:00','2018-09-01 17:00:00');
您还可以在插入操作之前添加排除约束以对其进行验证:
--In order to use scalar values (e.g.: therapist) on gist indexes we need this extension
CREATE EXTENSION btree_gist;
--Now we can add our new constraint
--Be careful with timezone issues, tsrange will discard timezone data
ALTER TABLE availabilities
ADD EXCLUDE USING gist(therapist WITH =, tsrange(starttime, endtime) WITH &&);
有关范围运算符here的更多信息。