【问题标题】:Acting on the day of week在星期几执行
【发布时间】:2020-10-26 04:14:01
【问题描述】:

希望有人可以在这里提供一些建议,我正在使用 PostgreSQL 数据库。

此查询的目的是确定当前允许访问的用户。目标是提供日期和时间范围作为输入,并查看在指定日期和时间范围内可以被允许访问的用户帐户。

表格是这样设置的,“开始时间”和“结束时间”的时间列指定了允许用户的时间范围。然后是一周中每一天的布尔列,指定是否允许该用户在当天的时间范围内访问。

   [START TIME]    [END TIME]   [MON]   [TUES]     [WED]     [THURS]     [FRI]    [SAT]     [SUN]
    09:00:00       11:00:00     True     True      True       True       True     False     False 

现在,这看起来很简单,但在我看来,系统需要首先知道星期几,然后使用一个冗长的“case when”来表示“如果输入的日期是星期一和 table.mon = 此用户为 true,则此用户符合条件。

到目前为止,我有这样的事情:

DO $$
DECLARE 

--Specify 'variables'
active_date timestamp := '2020-10-4';
start_time time := '00:00:00';
end_time time := '23:59:00';
day_of_week text := to_char(active_date, 'day');

BEGIN
    CREATE TEMP TABLE temp_output ON COMMIT DROP AS
    select distinct
    date(account.lastupdated) as "Date",
    concat(to_char(account.start_time, 'HH:MI'), ' - ', to_char(account.end_time, 'HH:MI')) as "Time Range"
    from account
    where account.lastupdated >= active_date AND account.lastupdated < active_date + interval '1 day'
    and account.start_time >= start_time AND account.end_time <= end_time;
END $$;

SELECT * FROM temp_output;

我坚持的是,如果输入的日期对于返回的每一行都有一个布尔值“真”,那么输出应该只显示值。

类似:

case when day_of_week = 'sunday' and account.sun = "True" then ...
     when day_of_week = 'monday' and account.mon = "True" then...
     when day_of_week = 'tuesday' and account.tues = "True" then...

但是如何根据输入的日期为整个结果集实现这个逻辑呢?

【问题讨论】:

  • 也许处理这个问题的最好方法是在底部加上一个很长的 where 子句?其中 (day_of_week = 'sunday' and account.sun = True) 或 (day_of_week = 'monday' and account.mon = True) 或...

标签: sql postgresql


【解决方案1】:

如果您只需要确定某行是否与特定日期匹配,请检查相应的列是否为真。

-- Check if this is valid for Monday
where mon

正如您所发现的,在 SQL 中使用单个列来存储列表项效果不佳。

在传统 SQL 中,您需要一个连接表来存储这次应用的日期。

create table schedule (
  id bigserial primary key,
  start_time time not null,
  end_time time not null
);

create table schedule_days (
  schedule_id bigint not null references schedule(id),
  day text not null
);

insert into schedule (start_time, end_time) values ('09:00', '11:00');
insert into schedule_days (schedule_id, day) values
  (1, 'Mon'), (1, 'Tues'), (1, 'Wed'), (1, 'Thurs'), (1, 'Fri');

select *
from schedule s
join schedule_days sd on s.id = sd.schedule_id
where current_time between start_time and end_time
  and day = $1

我们可以通过使用枚举来存储日期来改进这一点。这确保只添加正确的值。它节省了存储空间,因为它们实际上存储为整数。并且可以继续作为字符串查询。

create type day_of_week as ('Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun');

create table schedule_days (
  schedule_id bigint not null references schedule(id),
  day day_of_week not null
);

或者,您可以使用单个 array column 来表示这些天。

create table schedule (
  id bigserial primary key,
  start_time time not null,
  end_time time not null,
  days day_of_week[] not null
);

insert into schedule (start_time, end_time, days)
  values ('09:00', '11:00', array['Mon', 'Tues', 'Wed', 'Thurs', 'Fri']);

然后在标准化输入后,检查它是否包含在 days 数组中。

select *
from schedule s
where current_time between start_time and end_time
  and days @> array['Tues']

【讨论】:

  • 感谢您的洞察力。不幸的是,我没有创建(也没有维护)这个数据库。这是一个中等受欢迎的应用程序的数据库,他们正在外包我为他们创建报告......所以我在这里!
  • @boog 在这种情况下,要确定它是否对特定日期有效,只需检查相应的日期列是否为真。 where mon 检查周一是否有效。
猜你喜欢
  • 2013-12-31
  • 1970-01-01
  • 2011-10-31
  • 2016-10-22
  • 2015-05-13
  • 2022-08-10
  • 1970-01-01
  • 1970-01-01
  • 2022-07-08
相关资源
最近更新 更多