How to get date: one month away from a specific date? - sql

I know that I can get the date from today such as
select CURRENT_DATE - INTERVAL '1 months';
But what if I need the first date specified. Something like
select '2017-05-08 00:00:00' - INTERVAL '1 months'?
I tried different things and can't get it to work.

You could use:
select '2017-05-08 00:00:00'::DATE - '1 month'::INTERVAL
/\
|
cast as date
DBFiddle Demo

'2017-05-08 00:00:00' is a string literal. You need to convert it to a date, e.g., by using to_date:
SELECT TO_DATE('2017-05-08','yyyy-mm-dd') - INTERVAL '1 months'

Related

Select all rows with date column equal to today's date in postgres to the minute

I essentially want to run a query like:
SELECT * FROM t where date={time right now to the minute}
Use date_trunc() for your exact question:
where date = date_trunc('minute', now())
However, I suspect you really want the span of one minute:
where date >= date_trunc('minute', now()) and
date < date_trunc('minute', now()) + interval '1 minute'

How to select all rows created in the last hour?

My query is
SELECT * FROM email_operation WHERE cdate = CURRENT_DATE and ctime >= (NOW() - INTERVAL '1 hour' )
to select all rows created at the last hour but it doesn't work. It throws an error at >=
SELECT * FROM email_operation WHERE cdate = CURRENT_DATE and ctime >= (NOW() - INTERVAL '12 hour' )
> ERROR: operator does not exist: time without time zone >= timestamp with time zone
LINE 1: ..._operation WHERE cdate = CURRENT_DATE and ctime >= (NOW() ...
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
> Time: 0.001s
Apparently ctime is a time column, so you can't compare it with a timestamp (which is what the error message tells you). You need to use current_time instead:
and ctime >= current_time - interval '1 hour'
Note that this won't work properly around midnight.
It seems you have split up date and time into two columns (which is a bad idea), but you can combine them to compare a timestamp:
and cdate + ctime >= current_timestamp - interval '1 hour'
If you want results in the past hour and you have separated the date and time components, then one method is:
WHERE (cdate + ctime) >= NOW() - INTERVAL '1 hour'
Note that this will even work between midnight and 1:00 a.m. Sadly, it probably won't use indexes. That might be an issue if you have lots of data. Here is one method that will at least use an index on cdate:
WHERE cdate IN (CURRENT_DATE, CURRENT_DATE - INTERVAL '1 day') AND
( (cdate + ctime) >= NOW() - INTERVAL '1 hour' )
where (cdate + ctime)::timestamp(0) >= (now() - interval '1 hour')

How to get min value of all cities of yesterday?

How to get min value(temp) of all cities of yesterday.
I want:
Indore:min value:yesterday date
Bhopal:min value:yesterday date
Mumbai:min value:yesterday date
In Postgres, you can do:
select name, min(temp)
from t
where write_date < current_date and
write_date >= current_date - interval '1 day'
group by name;
You can also write the where clause as:
where date_trunc('day', write_date) = current_date - interval '1 day'
However, using the function date_trunc() prevents the use of the index for the where clause.
select name, min(temp) from table
where date(write_date) BETWEEN TRUNC(SYSDATE - 1)
AND TRUNC(SYSDATE) - 1/86400
group by name
this will do your job

How do I determine the last day of the previous month using PostgreSQL?

I need to query a PostgreSQL database to determine records that fall within today's date and the last day of the previous month. In other words, I'd like to retrieve everything that falls between December 31, 2011 and today. This query will be re-used each month, so next month, the query will be based upon the current date and January 31, 2012.
I've seen this option, but I'd prefer to avoid using a function (if possible).
Both solutions include the last day of the previous month and also include all of "today".
For a date column:
SELECT *
FROM tbl
WHERE my_date BETWEEN date_trunc('month', now())::date - 1
AND now()::date
You can subtract plain integer values from a date (but not from a timestamp) to subtract days. This is the simplest and fastest way.
For a timestamp column:
SELECT *
FROM tbl
WHERE my_timestamp >= date_trunc('month', now()) - interval '1 day'
AND my_timestamp < date_trunc('day' , now()) + interval '1 day'
I use the < operator for the second condition to get precise results (read: "before tomorrow").
I do not cast to date in the second query. Instead I add an interval '1 day', to avoid casting back and forth.
Have a look at date / time types and functions in the manual.
For getting date of previous/last month:
SELECT (date_trunc('month', now())::date - 1) as last_month_date
Result: 2012-11-30
For getting number of days of previous/last month:
SELECT DATE_PART('days', date_trunc('month', now())::date - 1) last_month_days
Result: 30
Try this:
SELECT ...
WHERE date_field between (date_trunc('MONTH', now()) - INTERVAL '1 day')::date
and now()::date
...
Try
select current_date - cast((date_part('day', current_date) + 1) as int)
take from http://wiki.postgresql.org/wiki/Date_LastDay, and modified to return just the days in a month
CREATE OR REPLACE FUNCTION calc_days_in_month(date)
RETURNS double precision AS
$$
SELECT EXTRACT(DAY FROM (date_trunc('MONTH', $1) + INTERVAL '1 MONTH - 1 day')::date);
$$ LANGUAGE 'sql' IMMUTABLE STRICT;
select calc_days_in_month('1999-05-01')
returns 31
Reference is taken from this blog:
You can use below function:
CREATE OR REPLACE FUNCTION fn_GetLastDayOfMonth(DATE)
RETURNS DATE AS
$$
SELECT (date_trunc('MONTH', $1) + INTERVAL '1 MONTH - 1 day')::DATE;
$$ LANGUAGE 'sql'
IMMUTABLE STRICT;
Sample executions:
SELECT *FROM fn_GetLastDayOfMonth(NOW()::DATE);

Generating a series from a predefined date (PG)

I'm trying to generate a series of monthly dates from a starting date, which happens to be the date of the oldest user in my users table.
Whilst I can select some dates quite easily;
SELECT generate_series(
now(),
now() + '5 months'::interval,
'1 month'::interval);
and can select the date I need to start at:
SELECT to_date( to_char(CAST(min(created_at) AS DATE),'yyyy-MM') || '-01','yyyy-mm-dd') from users
How can I combine the two so that I'm selecting every month up until now?
Turns out, it can be even simpler. :)
SELECT generate_series(
date_trunc('year', min(created_at))
, now()
, interval '1 month') AS month;
FROM users;
More about date_trunc in the manual.
Or, if you actually want the data type date instead of timestamp with time zone:
SELECT generate_series(
date_trunc('year', min(created_at))
, now()
, interval '1 month')::date AS month;
FROM users;
Turns out it's pretty simple:
SELECT generate_series(
(SELECT to_date( to_char(CAST(min(created_at) AS DATE),'yyyy-MM') || '-01','yyyy-mm-dd') from users),
now(),
'1 month'::interval) as month;