Common way to compare timestamp in Oracle, PostgreSQL and SQL Server - sql

I am writing an SQL query which involves finding if timestamp falls in particular range of days.
I have written that in the PostgreSQL but it doesn't works in Oracle and SQL Server:
AND creation_date < (CURRENT_TIMESTAMP - interval '5 days')
AND creation_date >= (CURRENT_TIMESTAMP - interval '15 days')
Is there are common way to compare the timestamp across different databases?

I'm not a SQL Server expert but I know this works on Oracle and Postgres and I suspect it may work on MSSQL but have no way to test it ATM.
AND creation_date < (CURRENT_TIMESTAMP - interval '5' day)
AND creation_date >= (CURRENT_TIMESTAMP - interval '15' day)
Or if you are using the date type instead of timestamp, you could do this but I'm pretty sure it wouldn't work on MSSQL. And the DATE type is quite different between Oracle and Pg.
AND creation_date < CURRENT_DATE - 5
AND creation_date >= CURRENT_DATE - 15
As was noted in the comments for OMG Ponies, you can only add ints to Date types not timestamps. (Oracle silently casts the timestamp to date)

How to compare two timestamps in postgresql, the following returns true:
select to_timestamp('2010-01-01 10:10:85.123', 'YYYY-MM-dd HH:MI:SS.MS') <
to_timestamp('2012-01-01 10:10:85.123', 'YYYY-MM-dd HH:MI:SS.MS');
Returns true because the 2012 is after the 2010

I don't believe there is common syntax that'll work across all database engines. In SQL Server, you do it like this:
AND creation_date BETWEEN DateAdd(dd, -5, GetUtcDate()) AND DateAdd(dd, -15, GetUtcDate())
I'm not sure about Oracle...

Oracle (I have tested both of these solutions):
AND (creation_date BETWEEN sysdate-15 AND sysdate-6)
This syntax is also valid:
AND (creation_date BETWEEN current_timestamp - INTERVAL '15' DAY
AND current_timestamp - INTERVAL '6' DAY)
Note that SYSDATE and CURRENT_TIMESTAMP are synonymous (sort of - see comments).
Note that BETWEEN returns values inclusive of the bounds. Since you are looking for values which are >= date-15 but < date-5, you need to specify -15 to -6 when using BETWEEN. The answers using an upper bound of -5 with a BETWEEN expression are wrong.

select * from timing where (db_time < CURRENT_DATE) AND (db_time > (CURRENT_DATE - INTERVAL '1' DAY)) ;

Again this is specific for Oracle, assume intime is TIMESTAMP(3) data type, you can do this
select * from MYTABLE where intime >= to_timestamp('2014-10-01 7:00:56', 'YYYY-MM-dd HH24:MI:SS')

Related

Oracle Developer - Hour Between 1 and 12 error, works on one machine but not another

I am running into an issue where i have oracle developer on 2 machines, the same code runs successful on one but gives an "hour must be between 1 and 12" error on the other, same versions of Oracle on both.
The code snippet is below. Not sure why this would present differently, I should also note, on the machine it is failing on, is the machine i developed this on a year+ ago, and it worked fine then.
The objective of this item is based on when the script is run, if its after 0400, it runs for a date parameter of todays date >0400 for the time. if its before 0400 when run, it runs for yesterdays date >0400 until.
and cast(scn_time as timestamp) >= case when to_char(current_timestamp, 'HH24:MI:SS')
> ('04:00:00') then to_timestamp(to_char(trunc(sysdate)||' 04.00.00 AM')) else
to_timestamp(to_char(trunc(sysdate-1)||' 4.00.00 AM')) end
Any help would be appreciated.
As #Abra hinted, your two SQL Developer installations have different NLS_TIMESTAMP_FORMAT settings (In Tool->Preferences->Database->NLS). You shouldn't rely on NLS settings, or implicit conversions, as your currently are when you convert the truncated date to a string. You are also relying on your session time zone when you use CURRENT_TIMESTAMP - that could get different values depending on session settings too.
You don't need to convert to or from strings here, you can do:
and scn_time >= case
when extract(hour from current_timestamp) >= 4
then trunc(sysdate) + interval '4' hour
else
then trunc(sysdate) - interval '1' day + interval '4' hour
-- or: then trunc(sysdate) - interval '20' hour
end
or
and scn_time >= trunc(sysdate) + interval '1' hour * case
when extract(hour from current_timestamp) >= 4 then 4
else -20
end
or
and (
(extract(hour from current_timestamp) >= 4
and scn_time >= trunc(sysdate) + interval '4' hour)
or
(extract(hour from current_timestamp) < 4
and scn_time >= trunc(sysdate) - interval '20' hour)
)
This also makes it easier to add an upper limit:
and (
(extract(hour from current_timestamp) >= 4
and scn_time >= trunc(sysdate) + interval '4' hour)
or
(extract(hour from current_timestamp) < 4
and scn_time >= trunc(sysdate) - interval '20' hour)
and scn_time < trunc(sysdate) + interval '4' hour)
)
Casting scn_time to TIMESTAMP probably isn't necessary, and applying a function to a table column will usually prevent any index on it (except an FBI) from being used. If it's already a date then leave it alone and just make the right-hand side of the comparison a date too.
I've left CURRENT_TIMESTAMP in there for now, but you might want SYSTIMESTAMP (which isn't affected by your session settings); though it depends what data type scn_time actually is and what it represents. If that is recording the SCN time for tracking then it might be a timestamp already; in which case cast the right-hand side to the same data type. If it's a string then it shouldn't be, but if you're stuck with it then convert it to a date explicitly with to_date() and the appropriate format mask.

How to run PostgreSQL Query every day with updated values?

New to SQL, but trying to learn/do a job for a friend. I have a query set up that returns the number of bookings for the day. Example snippet:
...
WHERE be.event IN ('instant_approve', 'approve') AND TO_CHAR(be.created_at, 'yyyy-mm-dd') BETWEEN '2017-06-26' AND '2017-06-26';
Now, this query is set up for just today. How can I set this up so that tomorrow the query is executed for '2017-06-27' and so on? Is this possible?
Built-in function now() gives you a timestamp of the beginning of your transaction (CURRENT_TIMESTAMP pseudo-constant is its "alias", a part of SQL standard, but I prefer using the function).
Another function, date_trunc() gives you a "truncated" timestamp and you can choose, how to truncate it. E.g., date_trunc('day', now()) will give you the date/time of beginning of the current day.
Also, you can add or subtract intervals easily, so here is an example that gives you the beginning of the current and the next days:
select
date_trunc('day', now()) cur_day_start,
date_trunc('day', now() + interval '1 day') as next_day_start
;
Also, I would not use to_char() or anything else on top of created_at column -- this will not allow Postgres planner use index on top of this field. If you do want to use to_char(), then consider adding a functional index over to_char(created_at, 'yyyy-mm-dd').
Here is how I would retrieve records generated at July 26, 2017:
where
created_at between '2017-06-26' and '2017-06-27'
(implicit type casting from text to timestamps here)
This is equivalent to
where
created_at >= '2017-06-26'
and created_at <= '2017-06-27'
-- so all timestamps generated for July 26, 2017 will match. And for such query Postgres will use a regular index created for created_at column (if any).
"Dynamic" version:
where
created_at between
date_trunc('day', now())
and date_trunc('day', now()) + interval '1 day'
Use current_date built-in function in the between condition and it will work only for today's bookings.
.........
WHERE be.event IN ('instant_approve', 'approve') AND TO_CHAR(be.created_at, 'yyyy-mm-dd') =current_date;

BigQuery SQL WHERE Date Between Current Date and -15 Days

I am trying to code the following condition in the WHERE clause of SQL in BigQuery, but I am having difficulty with the syntax, specifically date math:
WHERE date_column between current_date() and current_date() - 15 days
This seems easy in MySQL, but I can't get it to work with BigQuery SQL.
Use DATE_SUB
select *
from TableA
where Date_Column between DATE_SUB(current_date(), INTERVAL 15 DAY) and current_date()
Remember, between needs the oldest date first
You should probably switch the two around - the syntax should be the following:
WHERE date_column BETWEEN DATE_ADD(CURRENT_DATE(), -15, 'DAY') AND CURRENT_DATE()
This works for me.
WHERE DATE(date_column) BETWEEN DATE(DATE_ADD(CURRENT_DATE(), -15, 'DAY'))
AND CURRENT_DATE()

How to find records from yesterdays time till todays time in sql?

I am trying to find records from yesterdays 10:30 PM till today's 10:30 PM with SQL query. Please help me with sql query to find such records.
Maybe its a duplicate question, if so please link me to that. Don't want any pl-sql function.
A simple way to do this is to subtract times and compare dates. So, one way is:
select t.*
from t
where trunc(datecol) = trunc(sysdate - 1.5/24);
It is more efficient to use a direct comparison (because Oracle can more readily use an index):
select t.*
from t
where datecol >= trunc(sysdate) - 1.5/24 and
datecol < trunc(sysdate) + 1 - 1.5/24;
Note: You can also use interval for this purpose, if you are less old-fashioned than I am:
select t.*
from t
where datecol >= trunc(sysdate) - interval '90' minute
datecol < trunc(sysdate) + interval '1' day - interval '90' minute;
You can get the yesterday date with SYSDATE - 1. You would need something like this:
SELECT ...
FROM ...
WHERE date_field BETWEEN SYSDATE-1 AND SYSDATE

How to list records with date from the last 10 days?

SELECT Table.date FROM Table WHERE date > current_date - 10;
Does this work on PostgreSQL?
Yes this does work in PostgreSQL (assuming the column "date" is of datatype date)
Why don't you just try it?
The standard ANSI SQL format would be:
SELECT Table.date
FROM Table
WHERE date > current_date - interval '10' day;
I prefer that format as it makes things easier to read (but it is the same as current_date - 10).
http://www.postgresql.org/docs/current/static/functions-datetime.html shows operators you can use for working with dates and times (and intervals).
So you want
SELECT "date"
FROM "Table"
WHERE "date" > (CURRENT_DATE - INTERVAL '10 days');
The operators/functions above are documented in detail:
CURRENT_DATE
INTERVAL '10 days'
My understanding from my testing (and the PostgreSQL dox) is that the quotes need to be done differently from the other answers, and should also include "day" like this:
SELECT Table.date
FROM Table
WHERE date > current_date - interval '10 day';
Demonstrated here (you should be able to run this on any Postgres db):
SELECT DISTINCT current_date,
current_date - interval '10' day,
current_date - interval '10 days'
FROM pg_language;
Result:
2013-03-01 2013-03-01 00:00:00 2013-02-19 00:00:00
The suggested answers already seem to solve the questions. But as an addition I am suggesting to use the NOW() function of PostgreSQL.
SELECT Table.date
FROM Table
WHERE date > now() - interval '10' day;
Additionally you can even specifiy the time zone which can be really handy.
NOW () AT TIME ZONE 'Europe/Paris'
Starting with Postgres 9.4 you can use the AGE function:
SELECT Table.date FROM Table WHERE AGE(Table.date) <= INTERVAL '10 day';
Just generalising the query if you want to work with any given date instead of current date:
SELECT Table.date
FROM Table
WHERE Table.date > '2020-01-01'::date - interval '10 day'
I would check datatypes.
current_date has "date" datatype, 10 is a number, and Table.date - you need to look at your table.
you can use between too:
SELECT Table.date
FROM Table
WHERE date between current_date and current_date - interval '10 day';