【发布时间】:2013-03-31 20:10:45
【问题描述】:
在 SQL 表 person_rate 中,我们存储了一个随时间变化的速率浮动值。列:
id (serial, PK)
person_id (int)
date_from (date)
rate (float)
(person_id, date_from) 是独一无二的,因为每天最多允许更改一次(可能是 PK,但这并不重要)
给定 person_id 的速率值在从date_from 日期到具有连续date_from 的下一个记录的时间域内有效,或者如果没有这样的记录,则到无限未来。示例:
id person_id date_from rate
101 1 2011-01-01 100.0
145 1 2012-01-01 180.0
193 1 2012-05-01 140.0
现在我需要一个 SELECT 查询,它为每个 person_id 返回一个 rate,对于某些给定的 $date 有效。假设 2012-03-01 是 180; 2012-05-02 是 140 等等。
我测试过的解决方案:
1) 条件date_from <= $date + 使用窗口函数rank() OVER (PARTITION BY person_id ORDER BY date_from DESC + 在超选中WHERE rank = 1
2) 类似于 1) 但使用 SELECT DISTINCT ON (person_id) 而不是将排名限制为 1
1) 和 2) 都表现不佳,EXPLAIN 表明 db 需要对每个 person_id 的所有记录进行排序,然后首先限制为 1。可能这种查询不能充分利用date_from上的索引?
IDEA - 添加一个date_to 列,这会有点多余,因为该值将是“连续记录的date_from,减去1天”(如果没有连续记录,则为+infty) .但是查询可以使用date_from <= $date AND date_to >= $date - 它可能对date_from 和date_to 上的索引具有良好的性能。
但我有点害怕在这种情况下如何管理数据完整性 - 如何设置一个 person_id 的 [ date_from .. date_to ] 间隔不应重叠的约束?
对于这种类型的查询,postgresql 的最佳解决方案是什么?负载是读取最多的,对 person_rate 表的写入不多。典型的查询需要在内部获取每月每一天的费率......
也许这个SQL query for index/primary key ordinal 与 pg 9.2 上的新索引可以以某种方式提供帮助?
【问题讨论】:
标签: sql postgresql