合并多行的值并删除。 Postgres SQL
Merge values from multiple rows and delete. Postgres SQL
我有 table 的用户可用性。每行都有一个 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。
已编辑
为了获得任何重叠行的最短开始时间和最长结束时间,您可以将 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。
我有 table 的用户可用性。每行都有一个 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。
已编辑
为了获得任何重叠行的最短开始时间和最长结束时间,您可以将 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。