I want to check if a metric is still missing 4 hours later and return a single record if it exists. I wrote a query that checks if there were metrics in the last 4 hours. But I need to check if there is a metric for a certain hour that was expected to load 4 hours before.
-- Returns records that appeared within the last 4 hours
select * from main.basic_metrics
where metric_name = 'common_metric'
and transaction_time > current_timestamp - interval 4 hours
The problem is that transaction_timeis in the following format 2019-10-30T12:00:00.000+0000 where mm ss are always zeros. So when I check it like transaction_time = current_timestamp - interval 4 hours it returns nothing since current_timestamp contains mm ss data.
How should I format timestamp to the format similar to transaction_time - 2019-10-30T12:00:00.000+0000 ?
UPD: There was a typo, mentioned in the comments below. fixed it
That should be very simple: cast the string to timestamp with time zone:
WHERE CAST(transaction_time AS timestamp with time zone)
> current_timestamp - INTERVAL '4 hours'
Try the following:
select * from main.basic_metrics
where metric_name = 'common_metric'
and transaction_time = date_trunc('hour',current_timestamp) - interval 4 hours
This is not necessarily the best query for what you're doing, but it does solve the problem you're having. My guess is that some version of "between" or > and < would solve it, however without knowing exactly how the "transaction time" is populated, I'm could only venture guesses.
The trick in my example is to "truncate" everything after the "hours" off of the current_timestamp using date_trunc()
Note: It helps a lot to realize that timestamps are NOT formatted. Timestamps are a single long integer field that happens to get formatted on your screen so you can make sense of it. Text comparisons are nearly always the wrong way to do things, and datetime aware functions are the preferred method of doing any comparison.
I have a hive table that contains a column called timestamp. The timestamp is a bigint field generated from java System.currenttimemillis(). I suppose it should be in UTC. Right now I am trying to select records from 1 hour ago. I know in MySQL you can do something like:
SELECT * FROM table WHERE datetimefield >= DATE_SUB(NOW(), INTERVAL 1 HOUR)
In hive, it seems like NOW() is missing. I did some searching and find unix_timestamp(). I should be able to get the current UTC time in milliseconds by doing a unix_timestamp()*1000.
So if i want to get records from 1 hour ago I am thinking about doing something like:
SELECT * FROM hivetable WHERE datetimefield >= (unix_timestamp()*1000-3600000);
Can someone suggest if it's the right way to approach this problem? Also what if I want to select like 1 day ago? Seems inconvenient to convert that to milliseconds. Any help or suggested readings will be highly appreciated. Thanks in advance for your help.
Yes unix_timestamp() gets you the seconds elapsed since Unix epoch. You can subtract 60*60*1000 milliseconds and compare your field to get the desired records.
For Hive 1.2.0 and higher you can use current_timestamp
select *
from hivetable
where
datetimefield >= ((unix_timestamp()*1000) - 3600000);
For 1 day,convert the milliseconds to date format and use date_sub
select *
from hivetable
where
from_unixtime(unix_timestamp(datetimefield,'MM-dd-yyyy HH:mm:ss')) >=
date_sub(from_unixtime(unix_timestamp()),1);
I wish to convert a single Oracle datetime value to minutes.
As an example, I need to convert the current date/time alone into minutes, i.e.:
select (sysdate)*24*60 from dual
but this is giving me an error.
I basically need to perform a check to see that a certain operation cannot be performed until 30 minutes before a particular date/start time, that exists in the database.
So if the Start Time in the DB is:
24/04/2014 22:00:00 and the current date/time (SYSDATE) is 24/04/2014 21:29:59,
then operation CANNOT be performed but if the current date/time (SYSDATE) is:
24/04/2014 21:30:00,
then operation CAN be performed.
You probably want something like
startTime - interval '30' minute >= sysdate
or
startTime >= sysdate + interval '30' minute
You could also subtract the two date values which gives you the number of days between them and multiply
(startTime - sysdate)*24*60 >= 30
but I generally find the interval notation clearer and easier to read. It's also easier to structure in a way that allows you to use indexes on columns like startTime.
select (sysdate - trunc(sysdate)) *24 *60 from dual
You seem to want to know if the seconds component of sysdate is 0. So, test for that:
where extract(second from sysdate) = 0
Oops, I misread the question. You just need a difference of 30 minutes. That is also easy:
where starttime <= sysdate + 30/(24*60)
When you add an integer to a datetime, it is interpreted as a number of days. The expression 30/(24*60) is an expression for half an hour measured in days.
I have a books table with a returned_date column. I'd like to see the results for all of the books with a returned date that occurred in the past week.
Any thoughts? I tried doing some date math, but Postgres wasn't happy with my attempt.
You want to use interval and current_date:
select * from books where returned_date > current_date - interval '7 days'
This would return data from the past week including today.
Here's more on working with dates in Postgres.
Assuming returned_date is data type date, this is simplest and fastest:
SELECT * FROM books WHERE returned_date > CURRENT_DATE - 7;
now()::date is the Postgres implementation of standard SQL CURRENT_DATE. Both do exactly the same in PostgreSQL.
CURRENT_DATE - 7 works because one can subtract / add integer values (= days) from / to a date. An unquoted number like 7 is treated as numeric constant and initially cast to integer by default (only digits, plus optional leading sign). No explicit cast needed.
With data type timestamp or timestamptz you have to add / subtract an interval, like #Eric demonstrates. You can do the same with date, but the result is timestamp and you have to cast back to date or keep working with timestamp. Sticking to date is simplest and fastest for your purpose. Performance difference is tiny, but there is no reason not to take it. Less error prone, too.
The computation is independent from the actual data type of returned_date, the resulting type to the right of the operator will be coerced to match either way (or raise an error if no cast is registered).
For the "past week" ...
To include today make it > current_date - 7 or >= current_date - 6. But that's typically a bad idea, as "today" is only a fraction of a day and can produce odd results.
>= current_date - 7 returns rows for the last 8 days (incl. today) instead of 7 and is wrong, strictly speaking.
To exclude today make it:
WHERE returned_date >= current_date - 7
AND returned_date < current_date
Or:
WHERE returned_date BETWEEN current_date - 7
AND current_date - 1
To get the last full calendar week ending with Sunday, excluding today:
WHERE returned_date BETWEEN date_trunc('week', now())::date - 7
AND date_trunc('week', now())::date - 1
BETWEEN ... AND ... is ok for data type date (being a discrete type), but typically the wrong tool for timestamp / timestamptz. See:
How to add a day/night indicator to a timestamp column?
The exact definition of "day" and "week" always depends on your current timezone setting.
What math did you try?
This should work
select * from books where current_date - integer '7'
Taken from PostgreSQL Date/Time Functions and Operators
Is there a TIMESTAMPDIFF() equivalent for PostgreSQL?
I know I can subtract two timestamps to get a postgresql INTERVAL. I just want the difference between the two timestamps in in hours represented by an INT.
I can do this in MySQL like this:
TIMESTAMPDIFF(HOUR, links.created, NOW())
I just need the difference between two timestamps in hours represented as an integer.
Solution works for me:
SELECT "links_link"."created",
"links_link"."title",
(EXTRACT(EPOCH FROM current_timestamp - "links_link"."created")/3600)::Integer AS "age"
FROM "links_link"
The first things popping up
EXTRACT(EPOCH FROM current_timestamp-somedate)/3600
May not be pretty, but unblocks the road. Could be prettier if division of interval by interval was defined.
Edit: if you want it greater than zero either use abs or greatest(...,0). Whichever suits your intention.
Edit++: the reason why I didn't use age is that age with a single argument, to quote the documentation: Subtract from current_date (at midnight). Meaning you don't get an accurate "age" unless running at midnight. Right now it's almost 1am here:
select age(current_timestamp);
age
------------------
-00:52:40.826309
(1 row)
Get fields where a timestamp is greater than date in postgresql:
SELECT * from yourtable
WHERE your_timestamp_field > to_date('05 Dec 2000', 'DD Mon YYYY');
Subtract minutes from timestamp in postgresql:
SELECT * from yourtable
WHERE your_timestamp_field > current_timestamp - interval '5 minutes'
Subtract hours from timestamp in postgresql:
SELECT * from yourtable
WHERE your_timestamp_field > current_timestamp - interval '5 hours'
Michael Krelin's answer is close is not entirely safe, since it can be wrong in rare situations. The problem is that intervals in PostgreSQL do not have context with regards to things like daylight savings. Intervals store things internally as months, days, and seconds. Months aren't an issue in this case since subtracting two timestamps just use days and seconds but 'days' can be a problem.
If your subtraction involves daylight savings change-overs, a particular day might be considered 23 or 25 hours respectively. The interval will take that into account, which is useful for knowing the amount of days that passed in the symbolic sense but it would give an incorrect number of the actual hours that passed. Epoch on the interval will just multiply all days by 24 hours.
For example, if a full 'short' day passes and an additional hour of the next day, the interval will be recorded as one day and one hour. Which converted to epoch/3600 is 25 hours. But in reality 23 hours + 1 hour should be a total of 24 hours.
So the safer method is:
(EXTRACT(EPOCH FROM current_timestamp) - EXTRACT(EPOCH FROM somedate))/3600
As Michael mentioned in his follow-up comment, you'll also probably want to use floor() or round() to get the result as an integer value.
You can use the "extract" or "date_part" functions on intervals as well as timestamps, but I don't think that does what you want. For example, it gives 3 for an interval of '2 days, 3 hours'. However, you can convert an interval to a number of seconds by specifying 'epoch' as the time element you want: extract(epoch from '2 days, 3 hours'::interval) returns 183600 (which you then divide by 3600 to convert seconds to hours).
So, putting this all together, you get basically Michael's answer: extract(epoch from timestamp1 - timestamp2)/3600. Since you don't seem to care about which timestamp precedes which, you probably want to wrap that in abs:
SELECT abs(extract(epoch from timestamp1 - timestamp2)/3600)
postgresql get seconds difference between timestamps
SELECT (
(extract (epoch from (
'2012-01-01 18:25:00'::timestamp - '2012-01-01 18:25:02'::timestamp
)
)
)
)::integer
which prints:
-2
Because the timestamps are two seconds apart. Take the number and divide by 60 to get minutes, divide by 60 again to get hours.
extract(hour from age(now(),links.created)) gives you a floor-rounded count of the hour difference.
To avoid the epoch conversion you could extract the days multiply them by 24 and add the extraction of hours to it.
select current_timestamp, (current_timestamp - interval '500' hour), (extract(day from (current_timestamp - (current_timestamp - interval '500' hour)) * 24) + extract(hour from (current_timestamp - (current_timestamp - interval '500' hour))));
For MySQL timestampdiff I don't know, but for MSSQL datediff(hour, start, end) the best equivalent in PostgreSQL is floor(extract(epoch from end - start)/3600), because in MSSQL select datediff(hour,'2021-10-31 18:00:00.000', '2021-10-31 18:59:59.999') return 0
This might sound crazy to a lot of developers who like to take advantage of database functions,
But after exhaustive problems thinking, creating and bugfixing applications for mysql and postgrsql with php comparing date functions, I've come to the conclusion (for myself), that the easiest way, that is the simplest with less SQL headaches is not to take advantage of any of them.
Why? because if you are developing in a middleware language like PHP, PHP has all of these functions, and they are easier to implement in the application ode as comparing integers. PostgreSQL timestamp is NOT == UNIX TIMESTAMP and MySQL's UNIX TIMESTAMP is NOT PostgresQL's or Oracles timestamp.. it gets harder to port if you use database timestamps..
so just use an integer, not a timestamp,
as the number of seconds since january 1st 1970 midnight. and never mind database timestamps.
, and use gmdate() and store everything as gmt time to avoid timezone issues.
if you need to search, sort or compare the day from other data, or the month or the year or the day of the week, or anything, in your application,
and INTEGER datatype for time_day, time_hour, time_seconds.. or whatever you wnat to index to be searched will make for smoother and more portable databases.
you can just use one field, in most instances: INTEGER time_created NOT NULL
(more fields in your database row is the only drawback to this solution that i have found, and that doesnt cause as many headaches, or cups of coffee :)
php's date functions are outstanding to compare dates,
but in mysql or postgresql, comparing dates ? nah.. use integer sql comparisons
i realize it may SEEM easier to use CURRENT_TIMESTAMP on an insert function. HA!
don't be fooled.
You cant do DELETE FROM SESSION_TABLE WHERE time-initialized < '2 days'
if time-intitialized is a postgresql timestamp.
but you CAN do:
DELETE FROM SESSION_TABLE WHERE time_initialized < '$yesterday'
As long as you set $yesterday in php as the integer of seconds since 1970 that yesterday was.
This is easier housekeeping of session records than comparing timestamps in postgresql select statements.
SELECT age(), SELECT extract(), and asbtime are headaches in an of themselves. this is just my opinion.
you can do addition, substraction, <, >, all with php date objects
_peter_sysko
U4EA Networks, Inc.