Postgresql在月份范围之间选择

Vip*_*kat 7 sql postgresql select date date-range

我有一个表,其中一列是'YYYY-MM-DD'格式的日期.我可以使用select来获取每月范围内的所有数据吗?假设我想要从2012-01-xx到2013-04-xx的所有数据.所以我基本上是在寻找类似下面给出的SQL查询:

SELECT * FROM table WHERE date IN BETWEEN '2012-01' AND '2013-04' (INVALID QUERY)
Run Code Online (Sandbox Code Playgroud)

由于每个月都以'01'开头,我可以修改上述查询来调整开始条件.

SELECT * FROM table WHERE date IN BETWEEN '2012-01-01' AND '2013-04' (INVALID QUERY)
Run Code Online (Sandbox Code Playgroud)

现在问题出现了结束日期.我必须手动计算给定月份的最后日期,考虑所有因素,如月份长度,闰年等,因为如果给定日期无效,查询将失败.所以目前我正在做这样的事情:

SELECT * FROM table WHERE date IN BETWEEN '2012-01-01' AND 'VALID_MONTH_END_DATE' (VALID Query)
Run Code Online (Sandbox Code Playgroud)

我想知道是否有办法避免这种有效的结束日期计算?

澄清

我已经想到了下个月的第一天,但​​即便如此,我还是要用一些逻辑来说,如果是十二月,下一个月就是明年一月.我想知道一个SQL唯一的解决方案是否可行?

ype*_*eᵀᴹ 13

最好避免BETWEEN日期范围比较.更好地使用>=,<因为它与日期和日期时间列/值一致.

一种方法(如果你可以在外部建立日期):

WHERE date >= DATE '2012-01-01' 
  AND date < DATE '2013-05-01'      --- first date of the next month
Run Code Online (Sandbox Code Playgroud)

您还可以使用日期算术:

WHERE date >= DATE '2012-01-01' 
  AND date < DATE ('2013-04-01' + INTERVAL '1 MONTH')
Run Code Online (Sandbox Code Playgroud)

OVERLAPS运营商:

WHERE (date, date) OVERLAPS
      (DATE '2012-01-01', DATE '2013-05-01')
Run Code Online (Sandbox Code Playgroud)

您还应该阅读Postgres文档:日期/时间函数和运算符

手册在这里解释了为什么OVERLAPS以这种方式工作:

每个时间段被认为代表半开间隔开始<=时间<结束,除非开始和结束相等,在这种情况下它代表单个时刻.这意味着例如仅具有共同端点的两个时间段不重叠.


sam*_* yi 5

这是报表环境中非常普遍的需求。我创建了几个函数来适应这些日期操作

CREATE OR REPLACE FUNCTION public.fn_getlastofmonth (
  date
)
RETURNS date AS
$body$
begin
    return (to_char(($1 + interval '1 month'),'YYYY-MM') || '-01')::date - 1;
end;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;
Run Code Online (Sandbox Code Playgroud)

然后您可以使用...

WHERE date >= '2012-01-01' 
  AND date < fn_getlastofmonth('2013-04-01') 
Run Code Online (Sandbox Code Playgroud)