在PostgreSQL中查询不包括周末的日期范围

njthzxwz  于 2023-02-12  发布在  PostgreSQL
关注(0)|答案(1)|浏览(260)

我有下面的postgresql表;

id   |        date_slot        
------+-------------------------
 1    | [2023-02-08,2023-02-15)
 2    | [2023-02-20,2023-02-26)
 3    | [2023-02-27,2023-03-29)

我想创建一个查询,返回包含在这些范围内的行,但不包括周末
例如,我所做的查询返回以下内容,但不排除周末。

SELECT * FROM table where '2023-02-11'::date <@ date_slot;
 id   |        date_slot        
------+-------------------------
 1    | [2023-02-08,2023-02-15)

2023-02-11是周末,所以不能返回结果。我该怎么做?

umuewwlo

umuewwlo1#

选择仅工作日daterange(不包括周末):

你可以使用extract()检查范围内的第一天是星期几,并从upper()-lower()知道它的长度,确定它是否会跨越周末:online demo

select * 
from test_table 
where '2023-02-11'::date <@ date_slot
and extract(isodow from lower(date_slot)
                        + (not lower_inc(date_slot))::int)
  +(  (upper(date_slot) - (not upper_inc(date_slot))::int)
     -(lower(date_slot) + (not lower_inc(date_slot))::int) ) < 6 ;

当你的范围具有不同的上下限包容性时,lower_inc()upper_inc()处理它们的布尔结果,当转换为int时,只是加上或减去一天,以说明它是否包含在范围中。
如果范围从周末开始或从一周中的任何其他一天持续太长时间,则该范围为周末或包括周末:

  • 4天,如果从星期一开始(isodow=1
  • 3天,如果从星期二开始(isodow=2
  • 2天,如果从星期三开始(isodow=3
  • 1天,如果从星期四开始(isodow=4
  • 0天,如果从星期五开始(isodow=5

这意味着范围开始日期和范围长度的isodow之和不能大于5,否则范围将不与周末重叠。
您还可以使用generate_series()枚举这些范围包含的日期,并查看它们是否包括星期六(6日)或星期日(0dow7isodow):

select * 
from test_table 
where '2023-02-11'::date <@ date_slot
and not exists (
  select true
  from generate_series(
          lower(date_slot) + (not lower_inc(date_slot))::int,
          upper(date_slot) - (not upper_inc(date_slot))::int,
          '1 day'::interval) as alias(d)
  where extract(isodow from d) in (6,7) );

仅基于工作日date选择记录:

第一条评论说对了

select * 
from table_with_dateranges dr, 
     table_with_dates d
where d.date <@ dr.date_slot
and extract(isodow from d.date) not in (6,7);

相关问题