justify_days working issue in postgresql - postgresql

I execute the justify_days() in postgres sql
SELECT justify_days(interval '100 month')
output
"8 years 4 mons"
But I am using subquery instead of 100
SELECT justify_days(interval '(SELECT 100) month')
it shows an error
How can I fix it?

Try this,
select 100 returns 100 as integer datatype, So you need to cast it as interval and concatenate like below
select justify_days(cast((select 100)||' month' as interval))
Result:
justify_days
interval
--------------
8 years 4 mons
FYI,
select cast((select 100)||' month' as interval)
gives the same output
Result:
justify_days
interval
--------------
8 years 4 mons

Related

How to get interval from day of week from timstamp field in a table in Postgresql?

I can do the follwoing in Postgres
select interval '5 day';
Which returns
5 days
Also I can do
select (EXTRACT(DOW from i.closed_on)) || ' day' from issues i;
that results in
5 day
3 day
7 day
But I need to be able to convert this result into intervals. So I am trying to find a way to run something like
select interval (EXTRACT(DOW from i.closed_on)) || ' day' from issues i;
This gives an error.
This may be what you want.
postgres=# select ((EXTRACT(DOW from now())) || ' day')::interval;
interval
----------
5 days
(1 row)

I want to covert interval to decimal in postgres and need this result? [duplicate]

This question already has answers here:
How do I convert an interval into a number of hours with postgres?
(8 answers)
Closed 5 years ago.
Hi i have same query in oracle
select ( TRUNC(b.pub_ts, 'MI') - DATE '1970-01-01')* 24 * 60 * 60,
TRUNC(b.pub_ts, 'MI') - DATE '1970-01-01'
from abctable b where b.blurb_id=344143
the output of query in oracle is this
and i have converted query in postgres and i want same result how can i get that , i have created the query for postgres but it is giveing interval not decimal output like oracle
select ( date_trunc('minute', b.pub_ts) - DATE '1970-01-01')* 24 * 60 * 60,
date_trunc('minute', b.pub_ts) - DATE '1970-01-01'
FROM abc b WHERE b.blurb_id=344143;
I have tried many solution . can you help me out.
I think are is right, I think it is a duplicate of How do I convert an interval into a number of hours with postgres?
If you check the accepted answer, the only thing different in the example below is, I added a division of 24.
SELECT EXTRACT(epoch FROM INTERVAL '1499990400 days 1206720:00:00')/24/60/60,
EXTRACT(epoch FROM INTERVAL '17361 days 13:58:00')/24/60/60;
returns
1500040680 and 17361.581944444442
which are exactly the values you want.
Your query should look along the lines of this:
SELECT
extract( epoch FROM date_trunc('minute', b.pub_ts) - DATE '1970-01-01'),
extract( epoch FROM date_trunc('minute', b.pub_ts) - DATE '1970-01-01')/86400
FROM abc b WHERE b.blurb_id=344143;

How to count days between 2 dates excluding Saturday and Sunday in Postgresql [duplicate]

This question already has answers here:
How to count days except Sundays between two dates in Postgres?
(2 answers)
Closed 5 years ago.
If do:
SELECT '2017-03-31'::DATE - '2017-03-01'::DATE AS daysCount
it returns days count between those dates. I need same but excluding all Saturdays and Sundays. How?
you can use dow to exclude them, eg:
t=# with i as (
select '2017-03-31'::DATE d1, '2017-03-01'::DATE d2
)
select count(1)
from i
join generate_series(d2,d1,'1 day'::interval) g on true
where extract(dow from g) not in (6,0);
count
-------
23
(1 row)
t=# with i as (
select '2017-04-30'::DATE d1, '2017-04-01'::DATE d2
)
select count(1)
from i
join generate_series(d2,d1,'1 day'::interval) g on true
where extract(dow from g) not in (6,0);
count
-------
20
(1 row)
If I correctly understand, you need this:
select count(*) from (
select EXTRACT(DOW FROM s.d::date) as dd from generate_series('2017-03-01'::DATE, '2017-03-31'::DATE , '1 day') AS s(d)
) t
where dd not in(0,6)

Simplify calculation of months between 2 dates (postgresql)

This question is asked many times and one of the suggested queries to get months between 2 dates is not working.
SELECT date_part('month',age('2016-06-30', '2018-06-30'))
The result of this query is 0. It should be 24 months. Because the months are 06 in both dates.
This works, but it is a bit clumsy compared to the sql server function:
SELECT date_part ('year', f) * 12 + date_part ('month', f)
FROM age ('2016-06-30', '2018-06-30') f
Like sql server (I think):
DATEDIFF(month, date1, date2)
Is there no simple way (like the above) to calculate the months between 2 dates in Postgresql? I prefer not to use a function if it is possible.
Unfortunately you already have the most elegant solution.
If you look at the documentation for extract (same as date_part):
https://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT
month
For timestamp values, the number of the month within the year (1 - 12) ; for interval values, the number of months, modulo 12 (0 - 11)
SELECT EXTRACT(MONTH FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 2
SELECT EXTRACT(MONTH FROM INTERVAL '2 years 3 months');
Result: 3
SELECT EXTRACT(MONTH FROM INTERVAL '2 years 13 months');
Result: 1
For your problem it would be nice if there was a version of month that wasn't modulo 12 but that doesn't exist.
The option you have (extract the year * 12 + month) is the best option there is.
Edit
If you do want to create a function then see the following two functions:
CREATE OR REPLACE FUNCTION get_months(i interval) RETURNS double precision AS $$
SELECT date_part ('year', i) * 12 + date_part ('month', i) ;
$$ LANGUAGE SQL IMMUTABLE;
SELECT get_months(age('2016-06-30', '2018-06-30'));
Or
CREATE OR REPLACE FUNCTION get_months(to_date date, from_date date) RETURNS double precision AS $$
SELECT date_part ('year', f) * 12 + date_part ('month', f)
FROM age (to_date, from_date) f;
$$ LANGUAGE SQL IMMUTABLE;
SELECT get_months('2016-06-30', '2018-06-30');
You can actually create both then just use whichever suits your code.
This will give you the # of months between two dates excluding days.
CREATE OR REPLACE FUNCTION get_months_between(to_date date, from_date date) RETURNS double precision AS $$
SELECT (date_part ('year', to_date) * 12 + date_part ('month', to_date)) - (date_part ('year', from_date) * 12 + date_part ('month', from_date))
$$ LANGUAGE SQL IMMUTABLE;

Dynamic (Column Based) Interval

How do I add a dynamic (column based) number of days to NOW?
SELECT NOW() + INTERVAL a.number_of_days "DAYS" AS "The Future Date"
FROM a;
Where a.number_of_days is an integer?
I usually multiply the number by interval '1 day' or similar, e.g.:
select now() + interval '1 day' * a.number_of_days from a;
I know this is a year old, but if you need to use a column to specify the actual interval (e.g. 'days', 'months', then it is worth knowing that you can also CAST your string to an Interval, giving:
SELECT now()+ CAST(the_duration||' '||the_interval AS Interval)
So the the original question would become:
SELECT now() + CAST(a.number_of_days||" DAYS" AS Interval) as "The Future Date" FROM a;
I prefer this way. I think its pretty easy and clean.
In Postgres you need interval to use + operator with timestamp
select (3||' seconds')::interval;
select now()+ (10||' seconds')::interval,now();
where you can use seconds, minutes, days, months...
and you can replace the numbers to your column.
select now()+ (column_name||' seconds')::interval,now()
from your_table;
Use make_interval()
SELECT NOW() + make_interval(days => a.number_of_days) AS "The Future Date"
FROM a;
But in general it might be a better idea to use a column defined as interval, then you can use any unit you want when you store a value in there.
To creating intervals those based on column values, I recommend to add two columns in your table. For example, column "period_value"::INT4 and column "period_name"::VARCHAR.
Column "period_name" can store the following values:
microsecond
milliseconds
second
minute
hour
day
week
month
quarter
year
decade
century
millennium
+--------------+-------------+
| period_value | period_name |
+--------------+-------------+
| 2 | minute |
+--------------+-------------+
Now you can write:
SELECT NOW() - (period_value::TEXT || ' ' || period_name::TEXT)::INTERVAL FROM table;
If we have field with interval string value such as '41 years 11 mons 4 days' and want to convert it to date of birth use this query :
UPDATE "february14" set dob = date '2014/02/01' - (patient_age::INTERVAL)
dob is date field to convert '41 years 11 mons 4 days' to '1972/10/14' for example
patient_age is varchar field that have string like '41 years 11 mons 4 days'
And this is query to convert age back to date of birth
SELECT now() - INTERVAL '41 years 10 mons 10 days';
Updating based on a column ID was a useful way to create some randomised test data for me.
update study_histories set last_seen_at = now() - interval '3 minutes' * id;