当前位置: 首页 > 面试题库 >

如何从保留在PostgreSql中只返回工作时间?

淳于坚壁
2023-03-14
问题内容

从如何在PostgreSql的预订表中找到第一次空闲时间的最佳答案中选择

create table reservation (during tsrange,
 EXCLUDE USING gist (during WITH &&)
 );

用于查找在给定日期和时间(2012年11月17日:在下面的示例中)开始的时间表中的间隔,它还可以查找周六,周日和公共假日。表中定义了公众假期

create table pyha ( pyha date primary key)

如何也排除周末和公共假期?

硬编码空闲时间作为查询之类的保留时间

with gaps as (
  select
    upper(during) as start,
    lead(lower(during),1,upper(during)) over (ORDER BY during) - upper(during) as gap
  from (
    select during
    from reservation
   union all values
     ('(,2012-11-17 8:)'::tsrange), -- given date and hour from which to find free work time
     ('[2012-11-17 0:,2012-11-18 24:)'::tsrange), -- exclude saturday
     ('[2012-11-18 0:,2012-11-19 8:)'::tsrange),  -- exclude sunday
     ('[2012-11-19 18:,2012-11-20 8:)'::tsrange),
     ('[2012-11-20 18:,2012-11-21 8:)'::tsrange),
     ('[2012-11-21 18:,2012-11-22 8:)'::tsrange),
     ('[2012-11-22 18:,2012-11-23 8:)'::tsrange),
     ('[2012-11-23 18:,2012-11-24 24:)'::tsrange),
     ('[2012-11-24 0:,2012-11-25 24:)'::tsrange), -- exclude saturday
     ('[2012-11-25 0:,2012-11-26 8:)'::tsrange)  -- exclude sunday
 ) as x
)
select *
  from gaps
where gap > '0'::interval
order by start

对于每个空闲时间范围,都需要在联合中有单独的行。

从给定的日期和时间开始,在工作日和工作时间(8:00 .. 18:00)中返回空闲时间的最佳方法是哪种?

更新

选择答案时,总是在8:00返还空闲时间。如何在指定开始日期的指定开始时间之前返回空闲时间,例如,如果开始时间为9,则不返回2012-11-19
9:00之前的空闲时间?开始时间可能只有值8,9,10,11,12,13,14,15,16或17

即使2012-11-19 8:00(如果有空)也应返回2012-11-19
9:00。仅在2012-11-19的9:00没有空闲时间并且在随后的工作日中第一次空闲8:00时,才应返回8:00。

我试图通过将 2012-11-19 9: 添加到两个地方来解决此问题,如下查询所示,但此查询仍在2012-11-19
8:00返回空闲时间。如何解决此问题,使其在2012-11-19 9:00返回空闲时间?

create table reservation (during tsrange,
 EXCLUDE USING gist (during WITH &&)
 );
create table pyha ( pyha date primary key);
with gaps as (
    select
        upper(during) as start,
        lead(lower(during),1,upper(during)) over (ORDER BY during) - upper(during) as gap
    from (
        select during
          from reservation
             where upper(during)>= '2012-11-19 9:'
       union all values
         ('(,2012-11-19 9:)'::tsrange)
        union all
        select
            unnest(case
                when pyha is not null then array[tsrange(d, d + interval '1 day')]
                when date_part('dow', d) in (0, 6) then array[tsrange(d, d + interval '1 day')]
                else array[tsrange(d, d + interval '8 hours'),
                           tsrange(d + interval '18 hours', d + interval '1 day')]
            end)
        from generate_series(
            '2012-11-19'::timestamp without time zone,
            '2012-11-19'::timestamp without time zone+ interval '3 month',
            interval '1 day'
        ) as s(d)
        left join pyha on pyha = d::date
    ) as x
)

select start,
   date_part('epoch', gap) / (60*60) as hours
  from gaps
where gap > '0'::interval
order by start

更新2

我尝试更新答案,但返回错误数据。完整的测试用例是:

create temp table reservation  ( during tsrange ) on commit drop;
insert into reservation values(
'[2012-11-19 11:00:00,2012-11-19 11:30:00)'::tsrange );

with gaps as (
    select
        upper(during) as start,
        lead(lower(during),1,upper(during)) over (ORDER BY during) - upper(during) as gap
    from (
        select during
          from reservation
        union all
        select
            unnest(case
                when pyha is not null then array[tsrange(d, d + interval '1 day')]
                when date_part('dow', d) in (0, 6) then array[tsrange(d, d + interval '1 day')]
                when d::date =  DATE'2012-11-19' then array[
                            tsrange(d, '2012-11-19 12:'),  -- must return starting at 12:00
                            tsrange(d + interval '18 hours', d + interval '1 day')]
                else array[tsrange(d, d + interval '8 hours'), 
                           tsrange(d + interval '18 hours', d + interval '1 day')]
            end)
        from generate_series(
            DATE'2012-11-19'::timestamp without time zone,
            DATE'2012-11-19'::timestamp without time zone+ interval '3 month',
            interval '1 day'
        ) as s(d) 
        left join pyha on pyha = d::date
    ) as x 
)

select start,
   date_part('epoch', gap) / (60*60) as tunde
  from gaps 
where gap > '0'::interval
order by start

观察到的第一行:

"2012-11-19 11:30:00"

预期的 :

"2012-11-19 12:00:00"

怎么修 ?


问题答案:

您可以使用generate_series()函数来掩盖非工作时间:

with gaps as (
    select
        upper(during) as start,
        lead(lower(during),1,upper(during)) over (ORDER BY during) - upper(during) as gap
    from (
        select during
        from reservation
        union all
        select
            unnest(case
                when pyha is not null then array[tsrange(d, d + interval '1 day')]
                when date_part('dow', d) in (0, 6) then array[tsrange(d, d + interval '1 day')]
                when d::date = '2012-11-14' then array[tsrange(d, d + interval '9 hours'), tsrange(d + interval '18 hours', d + interval '1 day')]
                else array[tsrange(d, d + interval '8 hours'), tsrange(d + interval '18 hours', d + interval '1 day')]
            end)
        from generate_series(
            '2012-11-14'::timestamp without time zone, 
            '2012-11-14'::timestamp without time zone + interval '2 week', 
            interval '1 day'
        ) as s(d) 
        left join pyha on pyha = d::date
    ) as x 
)
select *
    from gaps
where gap > '0'::interval
order by start

让我解释一些棘手的部分:

  • 您不必在表中插入星期六/日的日期,pyha因为您可以使用date_part('dow', d)功能。pyha仅在公共假期使用表。’dow’对于Sun或Sat分别返回0或6。
  • 公共假期和周六/周日可以表示为单个间隔(0..24)。工作日必须用两个间隔(0..8)和(18..24)表示,因此unnest()和array []
  • 您可以在generate_series()函数中指定开始日期和长度

根据您的更新,我添加了另一个问题whencase

when d::date = '2012-11-14' then array[tsrange(d, d + interval '9 hours'), tsrange(d + interval '18 hours', d + interval '1 day')]

这个想法是为开始日期(d::date = '2012-11-14')产生不同的时间间隔:(0..9)和(18..24)



 类似资料:
  • 问题内容: 我试图在使用UUID作为主键的PostgreSQL中保留一个实体。我尝试将其持久保存为普通的UUID: 有了以上,我得到这个错误: 我也尝试将UUID保留为byte []无济于事: 如果删除@Lob,我得到的错误与上面发布的错误相同。但是使用@Lob时,错误会稍微更改为: 无法完成如此简单的操作,我感到非常难过! 我正在将Hibernate 4.1.3.Final与PostgreSQL

  • 在FastAPI中,我使用了SQLAlchemy和Pydanic返回数据 这种方式可以帮助我规范化返回的模型,但是我想要将所有api统一返回格式为{"code":0,"msg":"success","data":{...}},使原本返回模型中User的模型置于data中,方便前端管理。 我尝试了使用FastAPI中间件来实现,但是在swagger等文档中无法识别返回模型User;如果重新定义一个通

  • 我在PostgreSQL 9.5中有以下UPSERT: 如果没有冲突,它会返回如下内容: 但如果存在冲突,则不会返回任何行: 如果没有冲突,我想返回新的列,或者返回冲突列的现有列<这能做到吗?如果是,怎么做?

  • 问题内容: 需要访问一个从PostgreSQL返回setof refcursor的过程。 我能够访问第一个对象,但不能访问其余对象,而不能访问其余对象。 这给了我第一个refcursor值,但是当我尝试使用第二个refcursor时给了我错误,我使用了这一行: 它给出了错误。还尝试了: 这也行不通。过程示例为: 请帮助我如何访问第二个对象。 问题答案: 表示您在调用时得到一个常规,其中每个“行”包

  • 问题内容: 我有一个角度应用程序,它有两个视图: 1)清单检视 2)详细视图 当您从列表视图中单击缩略图时,将转到详细信息视图,这是以下路线: 现在’listCtrl’控制器中有一个loadmore函数,用于加载 问题 :现在的问题是,如果单击loadmore后进入详细视图,然后又回到列表视图,则新加载的div消失了,如何保存它们? 问题答案: 更改路径时,负责该路径的控制器在加载路径时初始化,而