搜索一系列日期时间条目

时间:2016-12-06 03:53:55

标签: sql ruby-on-rails ruby postgresql

我有一个奇怪的问题,我正试图解决。

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

该项目将全天改变价格,所以周一从早上5点到下午1点,这是一个价格,从下午1点到下午5点是另一个价格。它在下午5点到下午6点之间不可用,第二天在晚上7点到凌晨2点之间。

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

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

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

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

如何处理表格中的行并确保它们是连续的?这类问题有名字吗?

1 个答案:

答案 0 :(得分:0)

我会使用范围类型。

作为一个例子,我假设您的表定义如下:

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的一个值而不是两个时间戳,则查询会更简单。我建议你这样做。