PostgreSQL日期范围查询

213

我想查询我的PostgreSQL数据库,以返回某个月份和年份的日期结果。换句话说,我想要一个月-年的所有值。

到目前为止,我唯一能做到的是这样:

SELECT user_id 
FROM user_logs 
WHERE login_date BETWEEN '2014-02-01' AND '2014-02-28'

问题在于我需要在查询表格之前计算第一个日期和最后一个日期。是否有更简单的方法可以做到这一点?

谢谢。


间隔总是一个月吗?还是可能从15日开始,到下个月的7日结束? - frlan
5个回答

320

如果您使用 >= 开始时间 AND < 结束时间,在处理日期(和时间)时许多事情会变得更加简单。

例如:

SELECT
  user_id
FROM
  user_logs
WHERE
      login_date >= '2014-02-01'
  AND login_date <  '2014-03-01'

在这种情况下,您仍然需要计算所需月份的开始日期,但可以通过多种方式轻松完成。

结束日期也更简单;只需添加一个月即可。不必担心 28 日、30 日、31 日等问题。


这种结构还具有维护索引使用的优点。


许多人可能会建议使用以下形式,但它们使用索引:

WHERE
      DATEPART('year',  login_date) = 2014
  AND DATEPART('month', login_date) = 2

这涉及计算表中每一行的条件(扫描),而不是使用索引找到将匹配的行范围(范围查找)。


1
第一种方法需要处理月份(而不是天数),例如 2014-12-012015-01-01。第二种方法也可以进行索引,但这并不容易,我承认 -- EXTRACT() 似乎更兼容。 - pozs
4
你可以通过使用时间间隔(interval)来避免在应用程序中进行日期计算。例如:WHERE login_date >= '2014-02-01' AND login_date < '2014-02-01'::date + INTERVAL '1 month'这仍然可以使用索引,同时简化你的代码。 - baswell
@MatBailie,特别感谢您提供的DATEPART提示! - sunsetjunks
完美的答案! - Gaurav
datepart函数不存在 - 它被称为date_part()。 - undefined

92

从PostgreSQL 9.2开始支持区间类型。所以你可以这样写:

SELECT user_id
FROM user_logs
WHERE '[2014-02-01, 2014-03-01]'::daterange @> login_date

这应该比字符串比较更有效率。


10
对于具有TimeStamp类型的login_date: 选择user_logs中的user_id, 其中'[2014-02-01, 2014-03-01]'日期范围包含login_date的日期部分。 - All2Pie
1
能否构建一个动态范围?我想要进行INNER JOIN操作,检查第二个表中两个属性之间的时间戳是否在第一个表中。 - manuelnucci
2
看起来 tsrange(lower-bound, upper-bound) 就可以解决问题了! - manuelnucci
1
非常有用,特别是当您想创建像 [from, to)(from, to] 这样的范围时,确保左侧或右侧不匹配 equal 情况。 - George Dimitriadis

61

以防有人误入此处...自从8.1版本以来,您可以简单地使用以下方法:

SELECT user_id 
FROM user_logs 
WHERE login_date BETWEEN SYMMETRIC '2014-02-01' AND '2014-02-28'

文档中指出:

BETWEEN SYMMETRIC与BETWEEN相同,只是左侧的参数不需要小于或等于右侧的参数。如果不是这样,这两个参数会自动交换,以便始终隐含一个非空范围。


13
请注意,此查询包括 2014-02-28 00:00:00 - johnson
这里有一份文档,点击这里 - undefined

12
SELECT user_id 
FROM user_logs 
WHERE login_date BETWEEN '2014-02-01' AND '2014-03-01'

Between(之间)关键字在日期方面工作得非常好。它假设日期的时间为00:00:00(即午夜)。


9
请注意,此查询包括“2014-03-01 00:00:00”。 - johnson

-21

3
这并没有完全回答这个问题。这个问题是基于月份和年份来询问日期。 - Ram
也许这并不是回答问题的方法,但它解决了我的问题。虽然我有一个问题,如果结束日期是另一个月份,那么返回的数据将来自同一个月还是另一个月? - Pawan Tiwari

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接