Date subtraction in postgres - postgresql

I want to subtract minute from NOW() and the value of "how many minutes" I am reading from another table:
SELECT * FROM A, B
WHERE
A.entity_type_id = B.entity_type_id
AND A.status = 'PENDING'
AND A.request_time < (NOW() - INTERVAL B.retry_interval MINUTE)
AND A.retry_count >= B.retry_allowed_count
Here the problem is B.retry_interval is fetched from another table, while normally the queries like these are A.request_time < (NOW() - INTERVAL '10 MINUTE')
How do I achieve this?

Multiply the interval by interval '1 minute'
SELECT *
FROM A, B
WHERE
A.entity_type_id = B.entity_type_id
AND A.status = 'PENDING'
AND A.request_time < NOW() - B.retry_interval * INTERVAL '1 minute'
AND A.retry_count >= B.retry_allowed_count

I know its quite old enough, but here what i do. Btw my postgres version is 9.4.18.
try using interval data type. Convert the number from column to sting and concat it.
SELECT *
FROM A, B WHERE
A.entity_type_id = B.entity_type_id
AND A.status = 'PENDING'
AND A.request_time < (NOW() - concat(B.retry_interval::text,'minute')::interval
AND A.retry_count >= B.retry_allowed_count
Thanks to my coworker who find "interval" data type

Related

How to pass a parameterized INTERVAL in a slonik/postgres query?

This query seems to be legal when I run it in Datagrip with a parameter value of '14 days'
SELECT * FROM users WHERE users.updated_at < (CURRENT_DATE - INTERVAL $1)
But trying to do something similar in slonik as below does not:
const interval='14 days'
// ...
const {rows} = await pool.query<any>(sql`
SELECT * FROM users WHERE users.updated_at < (CURRENT_DATE - INTERVAL ${interval}))
`)
Seems to yield the same query: "SELECT * FROM users WHERE updated_at < CURRENT_TIME - INTERVAL $1)" but the pool's query method throws a syntax error near "$1" error when I try to execute it.
I've tried a couple of variations including escaping the input const interval="'14 days'" and adding parens for the INTERVAL function (CURRENT_DATE - INTERVAL(${interval})) with the same error results.
Is it not possible to parameterize a slonik query this way or am I doing something stupid?
You can subtract an integer representing the number of days from CURRENT_DATE because that is a date value not a timestamp
SELECT * FROM users WHERE updated_at < CURRENT_DATE - $1
Then pass $1 as an integer
Another option is to multiply an interval of a specific length with the parameter:
SELECT * FROM users WHERE updated_at < CURRENT_DATE - (interval '1 day' * $1)
or use the make_interval() function:
SELECT * FROM users WHERE updated_at < CURRENT_DATE - make_interval(days => $1)

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));

Postgres query timestamp by datepart only

I'm using this to try and get all events with a timestamp of today
SELECT systemuserid,ondate from auditlog
WHERE ondate::date = NOW()::date
Performance seems really bad, over 2 minutes. I have a index on ondate.
Is there a more efficient way to do it?
Thanks
Use a range condition:
select *
from auditlog
where ondate >= current_date
and ondate < current_date + 1;
current_date will be converted to a timestamp at midnight, so ondate => current_date will include everything from "today".
And the condition ondate < current_date + 1 will exclude rows with a timestamp of tomorrow (midnight) or later.

PostgreSQL - Difference between Current Date and a Date from Database

I'm trying to make a SELECT query which will compare current time with time at database. For example in database there is a record '2018-02-07 12:00:00' and I wanna compare it to current time. If current time is '2018-02-07 11:00:00', record '2018-02-07 12:00:00' should be visible in results. It should compare two dates and shows only those who are 1h before or after current time.'
Tried something like this:
SELECT * FROM events WHERE age(current_date, event_date) < '1 hour';
or
SELECT * FROM events WHERE event_date > (now() - INTERVAL '1 hour');
those that are 1h before or after current time
Wouldn't the logic look like this?
SELECT e.*
FROM events e
WHERE e.event_date > now() - INTERVAL '1 hour' AND
e.event_date < now() + INTERVAL '1 hour'

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.