我有一个预先存在的'events'表,其中包含event_datetime列和event_duration_minutes列。这两列分别是datetime和integer。
我最近遇到了在活动结束时触发电子邮件的需求。为了实现这一目标,我正在创建一个定期工作,每10分钟扫描一次数据库,查找最近完成的事件。因此,我开始编写查询以查找在给定时间窗口内已结束的所有事件,但由于每个记录的持续时间字段的可变性质,查询一直在逃避我。
我认为最好的方法是添加一个end_time列,然后自动将其设置为start_time + duration。这是正确的方法吗?
在任何情况下,我都会在如何进行查询方面留下完整的空白 - 是否有一种简单的方法可以解决这些问题?或者这种查询的一般需要是一个标志,表明您的数据库需要一些工作吗?
编辑 - 这是关于postgres 9.2。以下是我的rails schema.rb中的模式:
create_table "events", :force => true do |t|
t.string "title"
t.text "details"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.datetime "event_datetime"
t.integer "instructor_id"
t.integer "event_duration_minutes"
t.datetime "started_at_time"
end
答案 0 :(得分:2)
通常的解决方案是在计算的结束时间上创建表达式索引。然后,您可以轻松地对其进行索引搜索。
最简单的方法是定义一个简单的SQL函数,该函数执行计算,然后在表达式索引和要使用索引的查询中使用它。
例如:
CREATE OR REPLACE FUNCTION startduration_to_end(starttime timestamp, duration_minutes integer) RETURNS timestamp AS $$
SELECT $1 + $2 * INTERVAL '1' MINUTE';
$$ LANGUAGE sql;
然后:
CREATE INDEX mytable_end_index ON mytable
( (startduration_to_end(event_datetime,event_duration_minutes ) );
您可能在开始时间和结束时需要另一个,具体取决于查询模式,但如果您的表具有较高的更改率,请记住维护索引的成本:
CREATE INDEX mytable_end_index ON mytable
(event_datetime, (startduration_to_end(event_datetime,event_duration_minutes ) );
您可以使用startduration_to_end
函数查询这些索引,例如:
SELECT *
FROM mytable t
WHERE startduration_to_end(t.event_datetime,t.event_duration_minutes) BETWEEN current_timestamp - INTERVAL '10' MINUTE AND current_timestamp;
由于执行时间等的变化,您应该真正扫描搜索重叠的索引,或者搜索比上次搜索的确切时间戳更新的内容,而不是最后10分钟。