【问题标题】:How can I return records with calendar dates based on day of the week?如何根据星期几返回带有日历日期的记录?
【发布时间】:2017-03-29 14:20:54
【问题描述】:

我有以下架构:

时间表表示重复事件的时间表。

# Table name: schedules
#
#  id         :integer          not null, primary key
#  start_date :date
#  end_date   :date

Days 表示活动发生的时间表中的 WEEKdays。

# Table name: days
#
#  id          :integer          not null, primary key
#  schedule_id :integer
#  wday        :integer

TimeSlots 表示活动可能发生的时间(每天可能很多)。

# Table name: time_slots
#
#  id           :integer          not null, primary key
#  day_id       :integer
#  start_time   :time             not null
#  end_time     :time             not null

一个示例数据集,可以是:

  • 1 计划开始日期为 6 月 1 日,结束日期为 6 月 30 日
  • 1 天,宽度 wday = 0(活动发生在 6 月的每个星期一)
  • 2 个时隙。 1 与 start_hour 8am 和 end_hour 11am。另一个是 start_hour 1pm 和 end_hour 3pm

鉴于上面的示例(在下面的 SQL 中表示),我想为 6 月的每个星期一返回一条记录,包括他们的日历日期。

2017 年 6 月有 4 个星期一,因此上面的示例如下所示:

 id | wday | calendar_date |
----+------+---------------+
  1 |    2 |    2017-06-05 |
  1 |    2 |    2017-06-12 |
  1 |    2 |    2017-06-19 |
  1 |    2 |    2017-06-26 |

谁能引导我朝正确的方向前进?

在下面设置 PSQL:

CREATE TABLE schedules (
    id integer NOT NULL,
    start_date date,
    end_date date);

CREATE TABLE days (
    id integer NOT NULL,
    schedule_id integer,
    wday integer);

CREATE TABLE time_slots (
    id integer NOT NULL,
    start_time time,
    end_time time,
    day_id integer);

INSERT INTO schedules (id, start_date, end_date) VALUES (1, '2017-06-01', '2017-06-30');
INSERT INTO days (id, schedule_id, wday) VALUES (1, 1, 0);
INSERT INTO time_slots (id, start_time, end_time, day_id) VALUES (1, '18:00', '19:00', 1);

【问题讨论】:

  • 你不必存储星期几 - 你可以select extract(dow from now())?..
  • 我正在处理现有的代码库。模式结构已经设置并正在使用中,使用 wday 来表示任何给定星期中给定日期的活动。
  • 一周中的第一天是星期日还是星期一?
  • 在 Postgresql 中星期一 = 0
  • 那么为什么 wday = 2?

标签: sql postgresql


【解决方案1】:
select     s.id, wday, start_date + g calendar_date
from       schedules s
cross join generate_series(0, end_date - start_date) g
join       days d on d.schedule_id = s.id
where      extract(isodow from start_date + g) - 1 = wday

http://rextester.com/GTPQ53700

注意事项:

  • 使用generate_series()可以生成行,其中DB中没有数据
  • 我假设您希望从星期一开始几周(因为它在您的表格中由 0 表示)。最接近这一点的是 PostgreSQL 中的 ISODOW,但它使用 1-7 表示周一至周日。 (另一方面,DOW 使用 0-6 表示星期日至星期一:所以星期从星期日开始,DOW。)
  • 这实际上不会调查time_slots。如果需要,请将以下谓词添加到您的 WHERE 子句中:

    and exists(select 1 from time_slots t where t.day_id = d.id)
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多