【问题标题】:SQL query to search by day/month/year/day&month/day&year etcSQL查询按日/月/年/日&月/日&年等搜索
【发布时间】:2011-09-11 20:17:03
【问题描述】:

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

日期时间事件示例

  • 我出生于 1930-06-09
  • 我在 1950 年 7 月 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 天到第 15 天之间的事件
  • 从第 3 天开始,将查找每个月和每年的第 3 天的事件(如果 from 为空且to 不为空,则相同)
  • 从 5 月 3 日到 6 月将查找每年 5 月 3 日到 6 月最后一天之间的事件

关于如何编写可维护查询的任何提示(不一定要快)?

我们想到的一些事情

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

【问题讨论】:

    标签: sql postgresql


    【解决方案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 &&);
    

    写出所有可能的 from、to 和 day/month/year 组合 - 不可维护

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

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

    但是使用上面提到的句号类型会好很多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-05
      • 2017-02-15
      • 1970-01-01
      • 2016-11-28
      相关资源
      最近更新 更多