How to get average between two dates in PostgreSql - postgresql

I'd like to get the average date between two dates in Postgres:
In SqlServer is done with this simple query:
SELECT DateAdd(ms, DateDiff(ms, date_begin, date_end)/2, date_begin)
For example:
SELECT DateAdd(ms, DateDiff(ms, getdate(), dateadd(d, 1, getdate()))/2, getdate())
Now I'd like to make the same query in postgres.
I try with something like
SELECT current_timestamp + ((SELECT ((DATE_PART('day', (current_timestamp + INTERVAL '1 day')::timestamp - current_timestamp::timestamp) * 24 +
DATE_PART('hour', (current_timestamp + INTERVAL '1 day')::timestamp - current_timestamp::timestamp)) * 60 +
DATE_PART('minute', (current_timestamp + INTERVAL '1 day')::timestamp - current_timestamp::timestamp)) * 60 +
DATE_PART('second', (current_timestamp + INTERVAL '1 day')::timestamp - current_timestamp::timestamp)||'second')::interval
but it does not work.
Is there a simpler way to make this simple operation in Postgres?

How about:
select date_begin + (date_end - date_begin)/2

Related

PostgreSQL - Add days to current_data with condition

I'm trying to add a day to current_date in between only when from hour is bigger then to hour
can any one help?
see code:
AND EXISTS(SELECT *
FROM jsonb_array_elements((${hours})::jsonb) hours(e)
WHERE hours.e->'active' = 'true'
AND now() BETWEEN
current_date +
(LEFT(hours.e->>'from', 2))::INTEGER * INTERVAL '1 HOUR' +
(RIGHT(hours.e->>'from', 2))::INTEGER * INTERVAL '1 MINUTE' AND
current_date +
// add day if from is bigger then to
(LEFT(hours.e->>'to', 2))::INTEGER * INTERVAL '1 HOUR' +
(RIGHT(hours.e->>'to', 2))::INTEGER * INTERVAL '1 MINUTE' )
a

PostgreSQL: Date Calendar Days Interval Scenario

I would like to print this table (displaying only 4 rows for brevity):
Dates
Period
01-MAR-2022
61
02-MAR-2022
61
03-MAR-2022
61
30-APR-2022
61
So far I have:
SELECT CAST(TRUNC(date_trunc('month',CURRENT_DATE) + interval '-2 month') AS DATE) + (n || 'day')::INTERVAL AS Dates
, date_trunc('month',CURRENT_DATE) + interval '-2 month' + INTERVAL '2 month' - date_trunc('month',CURRENT_DATE) + interval '-2 month' AS Period
FROM generate_series(0,61) n
Please help with a better way of generating the period and also replacing the hard-coded 61 in generate_series(0,61).
Thanks!
What are you actually trying to accomplish, it is not clear nor specified. BTW your query is invalid. It appears you looking to list each data from first date of 2 months prior to the last date of 1 month prior and the total number of days in that range. The following would give the first date, and using date subtraction gives the number of days.
with full_range( first_dt, num_days) as
( select date_trunc ('month', (current_date - interval '2 months'))::date
, date_trunc ('month', (current_date - interval '1 day'))::date -
date_trunc ('month', (current_date - interval '2 months'))::date
)
select *
from full_range;
With that in hand you can use the num_days with generate series with the expression
select generate_series(0, num_days-1) from full_range
Finally combine the above arriving at: (see demo)
with full_range( first_dt, num_days) as
( select date_trunc ('month', (current_date - interval '2 months'))::date
, date_trunc ('month', (current_date - interval '1 day'))::date -
date_trunc ('month', (current_date - interval '2 months'))::date
)
select (first_dt + n*interval '1 day')::date, num_days
from full_range
cross join (select generate_series(0, num_days-1) from full_range) gn(n);

How to use COALESCE with INTERVAL in PostgreSQL?

This is a syntax error, but didn't see what the correct syntax would be.
The goal is to handle the case where days is null.
SELECT * FROM tbl WHERE created_at > current_date - INTERVAL 'COALESCE(%days%, 999) DAY'
You can multiply COALESCE(%days%, 999) to an interval of 1 day:
SELECT * FROM tbl
WHERE created_at > current_date - COALESCE(%days%, 999) * INTERVAL '1 DAY'
Use make_interval()
SELECT *
FROM tbl
WHERE created_at > current_date - make_interval(days:=COALESCE(%days%, 999));

add time interval with value from selected column in postgres

I am new in Postgres and want to know if there is a better way to solve time interval problem in Postgres.
In MySQL i have:
Select STR_TO_DATE(start_time - interval (tkc + tct) second + interval 3 hour, '%Y-%m-%d %H:%i:%s') as start_time
from table
For Postgres I found and wrote query as:
select start_time - (interval '1 second' * (tkc + tct)) + interval '3 hour'
from table
Thanks for all the answers. Wonderful to be part of community.
I was able to solve this as below.
select start_time - ((tkc + tct)|| ' seconds')::interval + interval '3 hour' as start_time from table

Select today's (since midnight) timestamps only

I have a server with PostgreSQL 8.4 which is being rebooted every night at 01:00 (don't ask) and need to get a list of connected users (i.e. their timestamps are u.login > u.logout):
SELECT u.login, u.id, u.first_name
FROM pref_users u
WHERE u.login > u.logout and
u.login > now() - interval '24 hour'
ORDER BY u.login;
login | id | first_name
----------------------------+----------------+-------------
2012-03-14 09:27:33.41645 | OK171511218029 | Alice
2012-03-14 09:51:46.387244 | OK448670789462 | Bob
2012-03-14 09:52:36.738625 | OK5088512947 | Sergej
But comparing u.login > now()-interval '24 hour' also delivers the users before the last 01:00, which is bad, esp. in the mornings.
Is there any efficient way to get the logins since the last 01:00 without doing string acrobatics with to_char()?
This should be 1) correct and 2) as fast as possible:
SELECT u.login, u.id, u.first_name
FROM pref_users u
WHERE u.login >= now()::date + interval '1h'
AND u.login > u.logout
ORDER BY u.login;
As there are no future timestamps in your table (I assume), you need no upper bound.
Some equivalent expressions:
SELECT localtimestamp::date + interval '1h'
, current_date + interval '1h'
, date_trunc('day', now()) + interval '1h'
, now()::date + interval '1h'
now()::date used to perform slightly faster than CURRENT_DATE in older versions, but that's not true any more in modern Postgres. But either is still faster than LOCALTIMESTAMP in Postgres 14 for some reason.
date_trunc('day', now()) + interval '1h' slightly differs in that it returns timestamptz. But it is coerced to timestamp according to the timezone setting of the current session in comparison to the timestamp column login, doing effectively the same.
See:
Ignoring time zones altogether in Rails and PostgreSQL
To return rows for the previous day instead of returning nothing when issued between 00:00 and 01:00 local time, use instead:
WHERE u.login >= (LOCALTIMESTAMP - interval '1h')::date + interval '1h'
select * from termin where DATE(dateTimeField) >= CURRENT_DATE AND DATE(dateTimeField) < CURRENT_DATE + INTERVAL '1 DAY'
This works for me - it selects ALL rows with todays Date.
select * from termin where DATE(dateTimeField) = '2015-11-17'
This works well for me!
An easy way of getting only time stamps for the current day since 01:00 is to filter with
CURRENT_DATE + interval '1 hour'
So your query should look like this:
SELECT u.login, u.id, u.first_name
FROM pref_users u
WHERE u.login > u.logout AND
u.login > CURRENT_DATE + interval '1 hour'
ORDER BY u.login;
Hope that helps.
where
u.login > u.logout
and
date_trunc('day', u.login) = date_trunc('day', now())
and
date_trunc('hour', u.login) >= 1
All answers so far are incorrect because they give the wrong answer between 0.00 and 1.00. So if you happen to run the query in that time period you get no results. Based on #ErwinBrandstetter's answer, what you want is this:
WHERE u.login > u.logout
AND u.login >= CASE WHEN NOW()::time < '1:00'::time THEN NOW()::date - INTERVAL '23 HOUR' ELSE NOW()::date + INTERVAL '1 HOUR' END;
I would love to do without the conditional but found no way to.
Edit: #ErwinBrandstetter did do it without a conditional, leaving this here for completeness.