Need to pull records from previous full hour regardless of time the query runs - sql

I want to pull records from the previous Full hour from when the query runs.
By this I mean regardless if it runs at 2:05 or 2:15 I will get records from 1:00:00 to 1:59:59.
Currently I get ORA-00907: missing right parenthesis error even though there are correct amount of parenthesis as far as I can tell. What am I doing wrong?
WHERE ((SS.NSAMPLE < SS.LSL OR SS.NSAMPLE > SS.USL) OR SS.FAILED = 'Y')
AND SD.DIMENSION_ID = SS.DIMENSION_ID
AND SUBDATE(STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H'), INTERVAL 1 HOUR) <= SS.SAMPLE_DATE AND SS.SAMPLE_DATE < STR_TO_DATE(DATE_FORMAT(NOW(), '%Y%m%d%H'), '%Y%m%d%H')
I also tried this and get the same missing right parenthesis error.
SUBDATE(SUBDATE(SUBDATE(SUBDATE(NOW(),
INTERVAL EXTRACT(MICROSECOND FROM NOW()) MICROSECOND),
INTERVAL EXTRACT(SECOND FROM NOW()) SECOND),
INTERVAL EXTRACT(MINUTE FROM NOW()) MINUTE),
INTERVAL 1 HOUR) <= SS.SAMPLE_DATE
AND SS.SAMPLE_DATE < SUBDATE(SUBDATE(SUBDATE(NOW(),
INTERVAL EXTRACT(MICROSECOND FROM NOW()) MICROSECOND),
INTERVAL EXTRACT(SECOND FROM NOW()) SECOND),
INTERVAL EXTRACT(MINUTE FROM NOW()) MINUTE)

You're using MySQL functions against an Oracle database. They are different database products, which both happen to be owned by Oracle Corp. (and have their documentation on docs.oracle.com), and the syntax varies. You might find the Oracle SQL Language Reference helpful.
To get data from the preceding hour in Oracle you can do:
AND SS.SAMPLE_DATE >= TRUNC(SYSDATE, 'HH') - INTERVAL '1' HOUR
AND SS.SAMPLE_DATE < TRUNC(SYSDATE, 'HH')
SYSDATE gives you the system time, e.g. 2022-12-21 17:30:37
TRUNC(SYSDATE, 'HH') gives you the system time truncated to the hour, e.g. 2022-12-21 17:00:00
TRUNC(SYSDATE, 'HH') - INTERVAL '1' HOUR gives you the system time truncated to the hour, with an hour subtracted, e.g. 2022-12-21 16:00:00
The two filter conditions then look for values greater than or equal to the previous hour, and less than (but not including) this hour, so effectively for that example system time:
AND SS.SAMPLE_DATE >= timestamp '2022-12-21 16:00:00'
AND SS.SAMPLE_DATE < timestamp '2022-12-21 17:00:00'
which covers all of the possible times in that hour-long period.
fiddle
The "ORA-00907: missing right parenthesis" error doesn't always mean you have the wrong number of parentheses. It means the parser got to a point where the next thing it expected to see was a right parenthesis, and it saw something else instead. It can have a variety of sometime non-obvious underlying problems.
In this case it's actually the interval syntax that's confusing it - if you change INTERVAL 1 HOUR to INTERVAL '1' HOUR to make it a valid Oracle interval literal then the error will change to "ORA-00904: "STR_TO_DATE": invalid identifier", which is easier to understand, as that's one of the MySQL functions that doesn't exist in Oracle.

Related

How to get an accurate number of results when selecting records from a period of time

I have a problem very similar to this StackOverflow question in that I need a full seven days of records. My query looks something like this:
SELECT id, entry_timestamp
FROM entries
WHERE created_on >= TO_DATE('2023-01-25', 'YYYY-MM-DD') at time zone 'UTC' - interval '7 days'
ORDER BY entry_timestamp
In my table entry_timestamp is a "timestamp without timezone" column and created_on is a "date" column.
(I need the TO_DATE() instead of current_date because I need to be able to specify a particular date)
When I run that query I get results with entry_timestamp from the last six days.
If I change it to interval '8 days' I get ten days for some reason.
What am I missing that is causing such a broad miscalculation?

Different query results while using DATE_TRUNC function in WHERE clause

I have a SQL query which gives different set of result when I use condition
DATE_TRUNC('DAY', timestamp) BETWEEN date_trunc('DAY', NOW()) - interval '14' day AND date_trunc('DAY', NOW())
and a different result when I use condition
timestamp BETWEEN date_trunc('DAY', NOW()) - interval '14' day AND date_trunc('DAY', NOW())
After cross checking both the query results I found that first condition is giving correct result.
Can someone please tell me the difference between both the conditions.
Thanks in advance
timestamp has a time component.
date_trunc(day, timestamp) removes the time component.
The second part of the comparison is different. The first version returns any time on the current day.
The second version only returns midnight on the current day.
Incidentally, I would recommend:
where timestamp >= current_date - interval '14 day' and
timestamp < current_date + interval '1 day'
This works, regardless of whether the timestamp column has a time component or not. And, it is friendly to the optimizer and index usage.

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 a query for every date for last 3 month

I have a table(pkg_date) in redshift. I want to fetch some data for every date for the last 3 months.
Here is my query
select * from pkg_data where scan_date < current_date;
How can I use current_date as a variable in the query itself and run this query for every date from April 1.
I have set a cron job which will run in every hour. In every hour it should run with different current_date
SELECT *
FROM pkg_data
WHERE scan_date > CURRENT_DATE - INTERVAL '3 months'
Be careful — Redshift works in UTC, so the CURRENT_DATE might suffer from timezone effects and be +/- what you expect sometimes.
SELECT
CURRENT_DATE,
(CURRENT_DATE - INTERVAL '3 months')::date
Returns:
2018-06-21 2018-03-21
Also be careful with strange lengths of months!
SELECT DATE '2018-05-31' - INTERVAL '3 months'
returns:
2018-02-28 00:00:00
Notice that it gave the last day of the month (31st vs 28th).
By the way, you can use DATE '2018-05-31' or '2018-05-31'::DATE, and also INTERVAL '3 months' or '3 months'::INTERVAL to convert types.
Use dateadd() for getting date 3 moth old day and GETDATE() for get current date.
ie code will look like.
select * from pkg_data where scan_date < dateadd(month,-3,GETDATE());
for cron refer How to execute scheduled SQL script on Amazon Redshift?

How to convert a single Oracle datetime into minutes?

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.