我想抓住ℕ月前创建的所有记录,完全相同的时间。 (记录年龄应仅为ℕ月,0天,0小时)
ℕ= {1,2,...}
例如,如果now()
为2016-11-15 13:15:00
,则预计会返回任何具有以下create_date的记录。
2010-11-15 13:15:00 -- different year
2016-02-15 13:15:00 -- different month
2016-11-15 13:46:23 -- different minute/seconds
2010-11-15 13:46:23 -- different year, month, minute and sec
我能想到的最简单的查询是:
SELECT *
FROM mytable
WHERE extract(day from age(now(), created_date)) = 0 -- same day any month ago
AND extract(hour from age(now(), created_date)) = 0; -- same hour
但问题是有一些特定日子将被排除在查询之外。比如什么时候
created_date=2016-01-31 13:00:00
now() is 2016-02-28 13:00:00
在这种情况下,记录的年龄为28 days
而不是1个月;根据Postgresql中的age
函数。
所以它永远不会在2月底或3月1日被取出。
对于如何以最简单的方式解决这个问题的任何想法都表示赞赏。
以下是您可以用来验证的一些测试数据:
create table mytable (created_date timestamp, expected_records int);
truncate mytable;
insert into mytable (created_date, expected_records) values
('2013-01-11 13:22:33', 2),
('2014-02-11 13:58:22', 2),
('2015-03-21 13:22:00', 1),
('2013-02-28 13:11:00', 5),
('2017-02-28 13:22:00', 5),
('2016-03-31 13:22:00', 5),
('2015-04-30 13:22:00', 5),
('2014-05-31 13:22:00', 5),
('2014-05-31 12:22:00', 1);
最终的SELECT查询可以在任何这些timstamp上执行,但应返回与expected_records
个状态相同的行数。
此外,您可以使用'some date'::timestamp
代替now()伪造时间。
答案 0 :(得分:1)
您可以通过获取第一个月 - (1天)来解决问题:
<强>样品:强>
t=# create table so42(t timestamp);
CREATE TABLE
t=# insert into so42 select '2016-05-31 13:00:00';
INSERT 0 1
t=# insert into so42 select '2016-10-31 13:00:00';
INSERT 0 1
t=# insert into so42 select '2016-02-29 13:00:00';
INSERT 0 1
t=# insert into so42 select '2016-01-21 13:00:00';
INSERT 0 1
加入示例:
t=# with ts as (
select
generate_series('2016-01-01 13:00:00'::timestamp,'2016-12-01'::date,'1 month'::interval)
- '1 day'::interval
lastday
)
select t
from so42
join ts on ts.lastday = t
;
t
---------------------
2016-02-29 13:00:00
2016-05-31 13:00:00
2016-10-31 13:00:00
(3 rows)
你也可以用函数将其包装成函数,如:
t=# create or replace function so45(_ts timestamp) returns table (lastday timestamp) as
$$
declare
_start timestamp;
_stop timestamp;
begin
select date_trunc('year', _ts) + (_ts)::time +concat(extract(day from _ts),' days')::interval into _start;
select date_trunc('year', _ts) + (_ts)::time +concat(extract(day from _ts),' days')::interval + '12 month'::interval into _stop;
return query with ts as (
select
generate_series(_start,_stop,'1 month'::interval)
- '1 day'::interval
lastday
)
select * from ts order by 1;
end;
$$ language plpgsql
;
CREATE FUNCTION
加入示例:
t=# with ts as (select so45('2016-03-31 13:00:00'))
select t
from so42
join ts on ts.so45 = t
;
t
---------------------
2016-02-29 13:00:00
2016-05-31 13:00:00
2016-10-31 13:00:00
(3 rows)
t=# with ts as (select so45('2016-03-21 13:00:00'))
select t
from so42
join ts on ts.so45 = t
;
t
---------------------
2016-01-21 13:00:00
(1 row)
答案 1 :(得分:1)
请尝试以下代码段,该段经过测试并确认为有效...
SELECT *
FROM mytable
WHERE EXTRACT( HOUR FROM NOW() ) = EXTRACT( HOUR FROM created_date )
AND ( ( EXTRACT( DAY FROM NOW() ) = EXTRACT( DAY FROM created_date ) ) OR
( EXTRACT( DAY FROM DATE_TRUNC( 'MONTH', NOW() ) + INTERVAL '1 MONTH - 1 DAY' ) = EXTRACT( DAY FROM NOW() ) AND
EXTRACT( DAY FROM created_date ) >= EXTRACT( DAY FROM NOW() ) ) );
以下代码测试以查看两个日期具有相同的天数,无论其中一个日期是否为其月末。在那种情况下,不需要进一步测试日期......
EXTRACT( DAY FROM NOW() ) = EXTRACT( DAY FROM created_date )
以下代码测试NOW()
是否在月末......
EXTRACT( DAY FROM DATE_TRUNC( 'MONTH', NOW() ) + INTERVAL '1 MONTH - 1 DAY' ) = EXTRACT( DAY FROM NOW() )
以下代码测试以查看created_date
的天数值是否大于NOW()
...
EXTRACT( DAY FROM created_date ) >= EXTRACT( DAY FROM NOW() )
因此,如果NOW()
的结尾的值不大于created_date
的日值,那么它们可以被认为是等价的(因此以下代码),例如NOW()
的日期= 2017-02-28与created_date
的2017-01-31,或NOW()
的约会= 2017-04 -30对比created_date
&#39; 2017-12-31等
EXTRACT( DAY FROM DATE_TRUNC( 'MONTH', NOW() ) + INTERVAL '1 MONTH - 1 DAY' ) = EXTRACT( DAY FROM NOW() ) AND
EXTRACT( DAY FROM created_date ) >= EXTRACT( DAY FROM NOW() )
如果您有任何问题或意见,请相应发表评论。
答案 2 :(得分:1)
首先,让我们更好地了解您的要求。您需要所有记录,时间戳列(created_date
)和&amp;当前时间(now()
)具有以下关系:
created_date
有一天,大于now()
天
仅当now()
位于当月的最后一天时,但。SELECT *
FROM mytable
WHERE EXTRACT(hour FROM created_date) = EXTRACT(hour FROM now())
AND (EXTRACT(day FROM created_date) = EXTRACT(day FROM now())
OR CASE
WHEN EXTRACT(month FROM CURRENT_DATE + 1) <> EXTRACT(month FROM CURRENT_DATE)
THEN EXTRACT(day FROM created_date) > EXTRACT(day FROM now())
ELSE FALSE
END)
http://rextester.com/TXGCSI34243
注意:如果要为解决方案绑定timestamp
(实际上不使用now()
&amp; current_date
函数),请使用{{1测试绑定时间戳是否是其月份的最后一天。