给定一个 PostgreSQL 表,该表应该包含具有连续、非重叠 valid_range 范围的行,例如:

CREATE TABLE tracking (
    id INT PRIMARY KEY,
    valid_range TSTZRANGE NOT NULL,
    EXCLUDE USING gist (valid_range WITH &&)
);

INSERT INTO tracking (id, valid_range) VALUES
    (1, '["2017-03-01 13:00", "2017-03-31 14:00")'),
    (2, '["2017-03-31 14:00", "2017-04-01 00:00")'),
    (3, '["2017-04-01 00:00",)');

这将创建一个包含以下内容的表:
 id |                     valid_range
----+-----------------------------------------------------
  1 | ["2017-03-01 13:00:00-07","2017-03-31 14:00:00-06")
  2 | ["2017-03-31 14:00:00-06","2017-04-01 00:00:00-06")
  3 | ["2017-04-01 00:00:00-06",)

我需要查询在给定季度结束时作为有效行的行,其中我将“在一个季度结束时”定义为“日期更改为第一天之前的时刻新季度。”在上面的示例中,查询 2017 年第一季度的结束时间(第一季度结束于 2017-03-31 结束,第二季度开始于 2017-04-01),我希望我的查询仅返回 ID 为 2 的行。

在 PostgreSQL 中表达这种条件的最佳方式是什么?
SELECT * FROM tracking WHERE valid_range @> TIMESTAMPTZ '2017-03-31' 是错误的,因为它返回包含 2017-03-31 午夜的行,即 ID 1。
valid_range @> TIMESTAMPTZ '2017-04-01' 也是错误的,因为它跳过了在季度末实际有效的行(ID 2),而是返回 ID 为 3 的行,即新季度开始的行。

我试图避免在查询中使用类似 ...ORDER BY valid_range DESC LIMIT 1 的东西。

请注意,范围的结尾必须始终是独占的,我无法更改。

最佳答案

到目前为止我想出的最佳答案是

SELECT
    *
FROM
    tracking
WHERE
    lower(valid_range) < '2017-04-01'
    AND upper(valid_range) >= '2017-04-01'

这似乎相当于说“我想为这个查询反转这个 TSTZRANGE 列的边界的包容性/排他性”,这让我觉得我错过了更好的方法。如果它也否定了范围列上典型索引的好处,我不会感到惊讶。

关于sql - PostgreSQL:查询包含季度最后时刻的 tstzrange,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45245363/

10-13 07:52