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以这种方式工作:
每个时间段被认为代表半开间隔开始<=时间<结束,除非开始和结束相等,在这种情况下它代表单个时刻.这意味着例如仅具有共同端点的两个时间段不重叠.
这是报表环境中非常普遍的需求。我创建了几个函数来适应这些日期操作
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)