sql—处理“无限”时获取日期范围最短的行

sauutmhj  于 2021-07-24  发布在  Java
关注(0)|答案(1)|浏览(289)

考虑我的模式:

  1. CREATE TABLE t_date (
  2. t_date_id int PRIMARY KEY
  3. , valid_from date NOT NULL
  4. , valid_to date DEFAULT 'infinity'
  5. );

有时我会 valid_to 约会,有时我有 infinity 在那里。。。
如何正确过滤以获得范围最短的行?
我试过:

  1. (DATE_PART('day', valid_to::timestamp - valid_from::timestamp))

但结果是:

  1. PG::DatetimeFieldOverflow: ERROR: cannot subtract infinite timestamps`

我有筛选器来选择有效范围: valid_from <= ? AND valid_to > ? 其思想是以最短的范围获取(一)个有效行。

示例

  1. INSERT INTO t_date VALUES
  2. (1, '2020-01-01', '2020-09-01')
  3. , (2, '2020-01-10', '2020-01-12')
  4. , (3, '2020-01-15', 'INFINITY')
  5. , (4, '2020-01-16', 'INFINITY') -- shortest among infinities
  6. , (5, '2020-01-14', 'INFINITY')
  7. ;

如果今天是 11/jan 我希望得到 '2020-01-10' | '2020-01-12' 因为有效期是1月11日,最短的。
如果今天是 14/jan 我希望得到 '2020-01-01' | '2020-09-01' 因为它的有效期是1月14日和最短的。
如果今天是 17/jan 我希望得到 '2020-01-16' | 'INFINITY' .
如果后来我创造了 '2020-01-15' | '2059-01-15' ,应该返回,因为它比无限行短。

qacovj5a

qacovj5a1#

  1. SELECT *
  2. FROM t_date
  3. WHERE valid_from <= ?
  4. AND valid_to > ?
  5. ORDER BY NULLIF(valid_to, 'infinity') - valid_from
  6. , valid_from DESC -- tiebreaker: later start first
  7. -- , t_date_id -- optional additional tiebreaker
  8. LIMIT 1;

db<>在这里摆弄 NULLIF() 皈依者 'infinity'NULL ,所以整个表达式变成 NULL ,默认情况下最后排序 ASCENDING 命令。无限范围应该排在你任务的最后。
要打破无限范围之间的联系,请另外按 valid_from DESC -定义了什么 NOT NULL 所以我们不需要特殊的治疗 NULL 案例。作为一个(欢迎?)副作用,这也打破了其他长度相等的范围之间的联系,选择了最新的开始。
为了得到确定的结果,如果允许相同的范围,您可能需要添加另一个明确的tiebreaker(如pk列)。
相关:
将空值排序到表的末尾

相关问题