【问题标题】:Search a series of date time entries搜索一系列日期时间条目
【发布时间】:2016-12-06 18:36:48
【问题描述】:

我有一个奇怪的问题要解决。

在我的模型中,我有 start_timeend_time,我们将模型称为“成本”。它与一个项目相关联。

该商品将全天更改价格,因此周一早上 5 点到下午 1 点是一个价格,下午 1 点到下午 5 点是另一个价格。然后在下午 5 点到下午 6 点之间不可用,并且在晚上 7 点到第二天凌晨 2 点之间提供第三个价格。

表示这些数据并不难,我有一个包含成本和开始/结束时间的表。

问题是我有固定数量的项目,以及可变的时间成本。

我可以搜索和检查以确保我在单个时间段内有可用的项目,并确保它在该时间段内实际上是“可出租的”。

如何处理跨多行的查询(例如(下午 4 点 - 晚上 7 点,会失败,或早上 6 点 - 下午 3 点,会通过),以确保它在连续的时间间隔内可用?

您将如何检查表中的行并确保它们是连续的?这类问题有名称吗?

【问题讨论】:

  • 您好,如果您包含实际的表定义和完整的示例查询,即使是英文而不是 SQL,也会更容易回答您的问题。
  • 创建一小时或半小时的行,然后通过检查相应行的可用性来检查该项目是否可供出租。可以看看activity selection problem。

标签: sql ruby-on-rails ruby postgresql


【解决方案1】:

我会为此使用范围类型。

作为一个例子,我假设你的表是这样定义的:

CREATE TABLE item_data (
   id integer PRIMARY KEY,
   start_time timestamp with time zone NOT NULL,
   end_time timestamp with time zone NOT NULL,
   available boolean NOT NULL,
   price NUMERIC(10,2)
);

然后您可以在上午 6 点到下午 3 点之间查询项目 1 的可用性,如下所示:

WITH q(i) AS
   (SELECT tstzrange '[2016-12-06 06:00:00, 2016-12-06 15:00:00)')
SELECT
   COALESCE(
      /*
       * Calculate the sum of the lengths of the intersection
       * between the time intervals and our given interval.
       */
      sum(
         upper(tstzrange(start_time, end_time, '[)') * q.i)
         - lower(tstzrange(start_time, end_time, '[)') * q.i)
      ),
      interval '0 hours'
   )
   /*
    * The item is available all the time if the above sum
    * is equal to the length of the given interval.
    */
   = upper(q.i) - lower(q.i)
FROM item_data, q
WHERE item_data.id = 1
   /* only consider times where the item is available */
   AND item_data.available
   /* only consider times that overlap with our given interval */
   AND tstzrange(item_data.start_time, item_data.end_time, '[)') && q.i
GROUP BY q.i;

如果第 1 项始终可用,则返回 TRUE,否则返回 FALSE

查询假设数据是一致的,即在给定时间给定项目的当前状态不超过一个。

可以类似地处理其他查询,例如检查数据的一致性。

如果您选择将间隔表示为一个tstzrange 类型的值而不是两个时间戳,则查询会更简单。我建议你这样做。

【讨论】:

  • 对于以后看到这个的任何人,我在这里创建了一个 SQL 小提琴:sqlfiddle.com/#!15/442b0/2,它展示了 Laurenz 的答案。它适用于 Postgresql。我添加了 wday,以按星期几分隔。我正在研究我能为 SQLite 做些什么。
猜你喜欢
  • 1970-01-01
  • 2021-12-19
  • 2021-12-29
  • 1970-01-01
  • 2021-10-15
  • 1970-01-01
  • 2019-02-19
  • 1970-01-01
  • 2012-10-27
相关资源
最近更新 更多