如果时间戳落在指定的日期范围内,则更新时间戳

Updating timestamps if they fall within a specified date range

我目前正在使用 table,其中包含有关实体及其时间戳的信息。 架构看起来像这样 dat(id, created_time)id 作为主键。

如果时间戳介于周六凌晨 1 点到周一凌晨 1 点(不含)之间,我们希望将时间戳替换为周一凌晨 1 点。

我正在考虑使用 case 结构来查找时间戳落在星期六且时间大于 1:00.00 或时间戳落在星期日或时间戳落在星期一且时间小于 1:00.00 的实例比 1:00.00,并分配一个硬编码的日期和时间。

我认为这是一个常见问题,并且希望获得有关如何简化此问题的任何提示,或者是否存在可简化流程的功能。谢谢!

好吧,有几种方法可以做到这一点。我的答案都依赖于周日的会话可用 week_start7,并且 date_trunc 不支持 week_iso,因此没有始终安全的解决方案。

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

所以有两个测试 dayofweek 和一个 time 比较,它们在 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

然后是 CASE,我认为它实际上读起来更好:

    ,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 混在一起,太恶心了:

,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

然后有一个 BETWEEN 只使用 DATE_TRUNC

 ,column1 between dateadd('hour', 1, date_trunc('week', column1)) 
        and dateadd('hour', 25, date_trunc('week', column1)) as between_logic  

无论如何,你说更新,所以这给了我一个统一的结果,一个 SELECT 或 VIEW 需要的可以分成一个 WHERE 子句

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))