postgresql - Postgres 生日选择

标签 postgresql intervals date

我使用 Postgres 数据库。该数据库有一个包含用户的表,用户有生日(日期字段)。现在我想让所有在下周过生日的用户....

我的第一次尝试:SELECT id FROM public.users WHERE id IN (lange reeks) AND birthdate > NOW() AND birthdate < NOW() + interval '1 week'

但这并没有结果,显然是因为过年了。我该如何解决这个问题?

有谁知道 PG 在 29-02 岁生日时会发生什么情况?

最佳答案

我们可以使用一个 postgres 函数以一种非常好的方式来做到这一点。

假设我们有一个表peopledob 列中有出生日期,这是一个日期,我们可以创建一个函数来索引此列忽略年份。 (感谢 Zoltán Böszörményi ):

CREATE OR REPLACE FUNCTION indexable_month_day(date) RETURNS TEXT as $BODY$
  SELECT to_char($1, 'MM-DD');
$BODY$ language 'sql' IMMUTABLE STRICT;

CREATE INDEX person_birthday_idx ON people (indexable_month_day(dob));

现在,我们需要查询表和索引。例如,获取任何一年四月生日的所有人:

SELECT * FROM people 
WHERE 
    indexable_month_day(dob) >= '04-01'
AND 
    indexable_month_day(dob) < '05-01';

有一个陷阱:如果我们的开始/结束时间跨过一年边界,我们需要更改查询:

SELECT * FROM people 
WHERE 
    indexable_month_day(dob) >= '12-29'
OR 
    indexable_month_day(dob) < '01-04';

为了确保我们匹配闰日生日,我们需要知道我们是将它们向前或向后“移动”一天。在我的例子中,只匹配这两天更简单,所以我的一般查询如下:

SELECT * FROM people 
WHERE 
    indexable_month_day(dob) > '%(start)%'
%(AND|OR)%
    indexable_month_day(dob) < '%(finish)%';

我有一个 Django 查询集方法,它使这一切变得更加简单:

def birthday_between(self, start, finish):
    """Return the members of this queryset whose birthdays
    lie on or between start and finish."""
    start = start - datetime.timedelta(1)
    finish = finish + datetime.timedelta(1)
    return self.extra(where=["indexable_month_day(dob) < '%(finish)s' %(andor)s indexable_month_day(dob) > %(start)s" % {
        'start': start.strftime('%m-%d'),
        'finish': finish.strftime('%m-%d'),
        'andor': 'and if start.year == finish.year else 'or'
    }]

def birthday_on(self, date):
    return self.birthday_between(date, date)

现在,我可以做如下事情:

Person.objects.birthday_on(datetime.date.today())

只在前一天匹配闰日生日,或者只在后一天匹配:你只需要将 SQL 测试更改为 `>=' 或 '<=',而不调整开始/结束在 python 函数中。

关于postgresql - Postgres 生日选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6913719/

相关文章:

python - Pandas.Series.dtype.kind 对于 pd.interval 来说是 None

mysql - 计算成员(member)期限,直到现在或直到结束日期

ruby-on-rails - 如何使用 ActiveRecord 检索表中具有相应条目的日期?

ruby-on-rails - 事件管理员日期过滤器日期格式自定义

ruby-on-rails - 如何对 Rails 中多类数组中的某些值进行排序?

centos - PHP 无法连接到 CentOS 7 上的 PostgreSQL

php - 时间段中的时间段 (PHP)

sql - ON DELETE 触发器运行后未删除行

postgresql - 确定 SQLAlchemy 对象上的哪些字段是脏的

Mysql timestampdiff 重叠间隔之间的总和