'Updating timestamps if they fall within a specified date range
I'm currently working with a table which has information about entities and their timestamps.
The schema looks like this dat(id, created_time), with id as the primary key.
If a timestamp falls in between Saturday 1am to Monday 1am (exclusive), we'd like to replace the timestamp with Monday 1am.
I was thinking of using a case structure to find instances where the timestamp falls on Saturday and the time is greater than 1:00.00 or timestamp falls on Sunday or timestamp falls on Monday and the time is less than 1:00.00, and assign a hard coded date and time.
I figured this is a common problem and would love any tips for how to make this more streamlined or if there is a function that exists to simplify the process. Thanks!
Solution 1:[1]
Well there are a couple of way this can be done. My answers all rely on session vairable week_start being 7 for Sunday, and date_trunc does not support week_iso so there is no always safe solution.
alter session set week_start = 7;
SELECT
to_char(column1,'DY HH:MI') as t
,dayofweek(column1)=1 AND column1::time >= '01:00'::time as sun_after_1am
,dayofweek(column1)=2 AND column1::time < '01:00'::time as mon_before_1am
,iff(sun_after_1am OR mon_before_1am, dateadd('hour', 25, date_trunc('week', column1)), column1) as iff_answer
,case
when dayofweek(column1)=1 AND column1::time >= '01:00'::time
then dateadd('hour', 25, date_trunc('week', column1))
when dayofweek(column1)=2 AND column1::time < '01:00'::time
then dateadd('hour', 25, date_trunc('week', column1))
else column1
end as case_answer
,iff((dayofweek(column1)=1 AND column1::time >= '01:00'::time) OR (dayofweek(column1)=2 AND column1::time < '01:00'::time), dateadd('hour', 25, date_trunc('week', column1)), column1) as monster_iff_answer
,column1 between dateadd('hour', 1, date_trunc('week', column1))
and dateadd('hour', 25, date_trunc('week', column1))
FROM VALUES
('2022-03-31 09:09'::datetime),
('2022-03-28 08:09'::datetime),
('2022-03-28 00:12'::datetime),
('2022-03-27 23:33'::datetime),
('2022-03-27 01:01'::datetime),
('2022-03-27 00:02'::datetime)
ORDER BY column1;
| T | SUN_AFTER_1AM | MON_BEFORE_1AM | IFF_ANSWER | CASE_ANSWER | MONSTER_IFF_ANSWER | BETWEEN_LOGIC |
|---|---|---|---|---|---|---|
| Sun 00:02 | FALSE | FALSE | 2022-03-27 00:02:00.000 | 2022-03-27 00:02:00.000 | 2022-03-27 00:02:00.000 | FALSE |
| Sun 01:01 | TRUE | FALSE | 2022-03-28 01:00:00.000 | 2022-03-28 01:00:00.000 | 2022-03-28 01:00:00.000 | TRUE |
| Sun 23:33 | TRUE | FALSE | 2022-03-28 01:00:00.000 | 2022-03-28 01:00:00.000 | 2022-03-28 01:00:00.000 | TRUE |
| Mon 00:12 | FALSE | TRUE | 2022-03-28 01:00:00.000 | 2022-03-28 01:00:00.000 | 2022-03-28 01:00:00.000 | TRUE |
| Mon 08:09 | FALSE | FALSE | 2022-03-28 08:09:00.000 | 2022-03-28 08:09:00.000 | 2022-03-28 08:09:00.000 | FALSE |
| Thu 09:09 | FALSE | FALSE | 2022-03-31 09:09:00.000 | 2022-03-31 09:09:00.000 | 2022-03-31 09:09:00.000 | FALSE |
So there is an two tests for dayofweek and a time compare, which are OR'ed in an IFF
,dayofweek(column1)=1 AND column1::time >= '01:00'::time as sun_after_1am
,dayofweek(column1)=2 AND column1::time < '01:00'::time as mon_before_1am
,iff(sun_after_1am OR mon_before_1am, dateadd('hour', 25, date_trunc('week', column1)), column1) as iff_answer
then there is the CASE, which I think actually reads nicer:
,case
when dayofweek(column1)=1 AND column1::time >= '01:00'::time
then dateadd('hour', 25, date_trunc('week', column1))
when dayofweek(column1)=2 AND column1::time < '01:00'::time
then dateadd('hour', 25, date_trunc('week', column1))
else column1
end as case_answer
then there is the IFF mashed all together, which is gross:
,iff((dayofweek(column1)=1 AND column1::time >= '01:00'::time) OR (dayofweek(column1)=2 AND column1::time < '01:00'::time), dateadd('hour', 25, date_trunc('week', column1)), column1) as monster_iff_answer
and then there is a BETWEEN that just uses DATE_TRUNC
,column1 between dateadd('hour', 1, date_trunc('week', column1))
and dateadd('hour', 25, date_trunc('week', column1)) as between_logic
anyways, you said update, so this give me a unified result, which a SELECT or VIEW would need can be separated into a WHERE clause
UPDATE table_name
SET date_time_column = dateadd('hour', 25, date_trunc('week', date_time_column ))
WHERE date_time_column BETWEEN dateadd('hour', 1, date_trunc('week', date_time_column))
AND dateadd('hour', 25, date_trunc('week', date_time_column))
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Simeon Pilgrim |
