I have the following query in Postgres:
SELECT * FROM users WHERE registration = last_login;
Both registration and last_login are timestamps. The problem I have is that those two values are written with some tiny difference, but they are not exact. Is there any way I can compare those two dates with a margin of, say, 1 second?
a_horse_with_no_name actualy has answered your question but just for case when there's no guarantee one date is after another you could try something like this:
SELECT *
FROM users
WHERE #extract(epoch from registration - last_login) <= 1;
extract(epoch from some_interval) returns timestamp difference in seconds as a number, and #some_value returns absolute value of a number, just like abs(some_value)
Assuming that last_login is always after registration, you can check the difference between the two timestamps
select *
from users
where last_login - registration <= interval '1' second
Related
I have two timestamps and I would like to have a result with the difference between them. I found a similar question asked here but I have noticed that:
select
to_char(column1::timestamp - column2::timestamp, 'HH:MS:SS')
from
table
Gives me an incorrect return if these timestamps cross multiple days. I know that I can use EPOCH to work out the number of hours/days/minutes/seconds etc but my use case requires the result as a timestamp (or a string...anything not an interval!).
In the case of multiple days I would like to continue counting the hours, even if it should go past 24. This would allow results like:
36:55:01
I'd use the built-in date_part function (as previously described in an older thread: How to convert an interval like "1 day 01:30:00" into "25:30:00"?) but finally cast the result to the type you desire:
SELECT
from_date,
to_date,
to_date - from_date as date_diff_interval,
(date_part('epoch', to_date - from_date) * INTERVAL '1 second')::text as date_diff_text
from (
(select
'2018-01-01 04:03:06'::timestamp as from_date,
'2018-01-02 16:58:07'::timestamp as to_date)
) as dates;
This results in the following:
I'm currently unaware of any way to convert this interval into a timestamp and also not sure whether there is a use for it. You're still dealing with an interval and you'd need a point of reference in time to transform that interval into an actual timestamp.
I have table with created (timestamptz) property. Now, i need to create pagination based on timestamp, because while user is watching first page, new items could be submitted into this table, which will make data inconsistent in case if i'll use OFFSET for pagination.
So, the question is: should i keep created type as timestamptz or it's better to convert it into integer (unix, e.g. 1472031802812). If so, is there any disadvantages? Also, atm i have now() as default value in created - is there alternative function to create unix timestamp?
Let me rewrite things from comments to my answer. You want to use timestamp type instead of integer simply because that's exactly what it was designed for. Doing manual convertions between timestamp integers and timestamp objects is just a pain and you gain nothing. And you will need it eventually for more complex datetime based queries.
To answer a question about pagination. You simply do a query
SELECT *
FROM table_name
WHERE created < lastTimestamp
ORDER BY created DESC
LIMIT 30
If it is first query then you set say lastTimestamp = '3000-01-01'. Otherwise you set lastTimestamp = last_query.last_row.created.
Optimization
Note that if the table is big then ORDER BY created DESC might not be efficient (especially if called parallely with different ranges). In this case you can use moving "time windows", for example:
SELECT *
FROM table_name
WHERE
created < lastTimestamp
AND created >= lastTimestamp - interval '1 day'
The 1 day interval is picked arbitrarly (tune it to your needs). You can also sort results in the app.
If results is not empty then you update (in your app)
lastTimestamp = last_query.last_row.created
(assuming you've done sorting, otherwise you take min(last_query.row.created))
If results is empty then you repeat the query with lastTimestamp = lastTimestamp - interval '1 day' until you fetch something. Also you have to stop if lastTimestamp becomes to low, i.e. when it is lower then any other timestamp in the table (which has to be prefetched).
All of that is under some assumptions for inserts:
new_row.created >= any_row.created and
new_row.created ~ current_time
The distribution of new_row.created is more or less uniform
Assumption 1 ensures that pagination results in consistent data while assumption 2 is only needed for the default 3000-01-01 date. Assumption 3 is to make sure that you don't have big empty gaps when you have to issue many empty queries.
You mean something like this?
select extract(epoch from now())::integer as unix_time
I found a weird thing. If a timestamp value subtract another, then Redshift will return an strange prefix. For example,
select table1.c_timestamp - table1.c_timestamp from table_1
Expect result should be ZERO or similar something, because these two timestamp values are same.
However, what I received is "5012369 years 4 mons", which I have no idea how does Redshift calculate the result.
Is there anyone can show me some clues?
Thanks
Contrary to the other answer,
Datediff doesn't exactly subtract, but rather counts the number of times the datepart chosen starts between the two timestamps.
datediff(second, '2018-04-10 00:00:00.001','2018-04-10 00:00:00.999')
>> 0
select datediff(second, '2018-04-10 00:00:00.999','2018-04-10 00:00:01.001')
>> 1
See: Datediff documentation
Edit: this is the way I found of how to perform the OP's task
SELECT
round(((EXTRACT('epoch' FROM TIMESTAMP '2018-05-27 09:59:59.999') - EXTRACT('epoch' FROM TIMESTAMP '2018-05-27 09:59:59.001'))*1000 + EXTRACT(millisecond FROM TIMESTAMP '2018-05-27 09:59:59.999') - EXTRACT(millisecond FROM TIMESTAMP '2018-05-27 09:59:59.001'))::real/1000)
The right way to subtract between datetimes is:
select datediff(seconds, table1.c_timestamp, table1.c_timestamp) from table_1
Of course, it doesn't make much sense to subtract a timestamp from itself, because that obviously returns 0, but I assume you just run that as a test.
I have two columns, say "2010-10-26" and "2010-08-23" and I would like to obtain the interval in days, what is the best way to do this on a select query taking into account that there are months with 30,31,29,28 days? Is there any function that already does this?
Thank you.
If they are already in the date format, it's very easy:
SELECT '10/26/2010'::date - '08/23/2010'::date;
OR:
SELECT date '2001-10-01' - date '2001-09-28'; // outputs integer 3
I need to go through every row in a table and set every date in a particular column to the date before its current value (minus 14 hours, previous day, etc).
I could write a script to do this but I was wondering if there was a better SQL method?
Thanks!
UPDATE yourtable SET thefield = thefield - interval '14 hour';
relevant docs here, which should have been your first place to check.