按日/月/年/日以及月/日和年等搜索的SQL查询

时间:2011-06-09 15:50:02

标签: sql postgresql

我有一个包含事件的PostgreSQL数据库。每个事件都有一个日期时间或间隔。公共数据存储在events表中,日期存储在events_datesdatetime字段)或events_intervalsstarts_dateends_date中是date个字段)。

日期时间事件示例

  • 我出生于1930-06-09
  • 我在1950-07-12获得驾驶执照
  • 圣诞节是在1900-12-24(1900年保留用于年度重新安置活动)

采样间隔事件

  • 我将于2011-06-09至2011-07-23度假。

现在我有一个想要查找这些事件的用户。他们将能够填写包含fromto字段的表单,在这些字段中,他们可以输入完整日期,日期,月份,年份,日期和月份,日期和年份,月份和年份一个或两个领域。

示例查询

  • 从5月3日到2012年12月21日将查找5月3日至12月21日期间最长年份为2012年的活动
  • 从第3天到第15天,将查找每个月和第3天的第3天和第15天之间的事件
  • 从第3天起,将查找每个月和第3天的事件(如果from为空且to不为,则相同)
  • 从5月3日到6月,将查找5月3日至每年6月的最后一天之间的活动

有关如何编写maintanable查询的任何提示(它不一定非常快)?

我们想到的一些事情

  • 写下所有可能的fromto和日/月/年组合 - 不可维护
  • 将日期比较为字符串,例如输入:____-06-__其中_是通配符 - 我不必生成所有可能的组合,但这对于间隔不起作用

1 个答案:

答案 0 :(得分:1)

您可以使用pg / temporal扩展名来编写额外快速的可维护查询:

https://github.com/jeff-davis/PostgreSQL-Temporal

create index on events using gist(period(start_date, end_date));

select *
from events
where period(start_date, end_date) @> :date;

select *
from events
where period(start_date, end_date) && period(:start, :end);

您甚至可以使用它来禁止重叠作为表约束:

alter table events
add constraint overlap_excl
exclude using gist(period(start_date, end_date) WITH &&);

  

写下所有可能的,以及日/月/年组合 - 不是维护

它实际上比你想象的更容易维护,例如:

select *
from events
join generate_series(:start_date, :end_date, :interval) as datetime
on start_date <= datetime and datetime < end_date;

但使用上述句号类型要好得多。