Select specific timestamp interval across multiple dates - oracle

I have tried searches on Google and various other sites with no luck, even making the search terms as vague as possible.
I have a query with data across multiple days but I only want to select data that has the time between 21:45 and 22:45.
The temp table built with the whole data has the data column that was converted from to_date to to_char so changing it back to to_date or to_timestamp is necessary, I think.
The problem is I have tried both of those and get invalid month errors. For example to_date(complete_date, 'hh24:mi:ss') gives me the error.
I'm not sure how to filter for a timestamp interval without giving a hard coded date.
Many thanks in advance. I am using Oracle Sql and unfortunately I don't have the query at the moment. It's on the computer at work. If a reply comes and I am at work I can reply back with more information.
With details as (
select to_char(complete_date, 'yyyy-mm-dd hh24:mi:ss') complete_date,
to_char(complete_date, 'hh24:mi:ss') as ts from table
where complete_date between trunc(sysdate)-30 and trunc(sysdate) )
select * from details where ts between '21:45:00' and '22:45:00'

I was able to filter by timestamp by using:
Round(Extract(hour from to_timestamp(complete_date, 'yyyy-mm-dd hh24:mi:ss')) + (extract(minute from to_timestamp(complete_date, 'yyyy-mm-dd hh24:mi:ss'))/60),2) count_ts
Then filter for count_ts between 21.75 and 22.75. This will allow me to get any data between those times no matter the day.
Problem solved.

Related

Oracle SQL TO_DATE and TO_TIMESTAMP

I have two queries in Oracle SQL that are equivalent.
SELECT ... FROM TABLE WHERE timestamp = TO_DATE('2017-07-01', 'YYYY-MM-DD')
and
SELECT ... FROM TABLE WHERE
timestamp >= TO_TIMESTAMP('2017-07-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND
timestamp < TO_TIMESTAMP('2017-07-02 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
Generally, I need to run this everyday (automated) so the first query will suffice for the application. However, for the first few runs I need some custom date-time boundaries, so I might manually intervene and use the second query instead.
What I observed is that the first one run faster. Under the hood, is this really the case? Is the performance difference significant enough? Can someone explain?
Devil is in the details.
1) How many records in the table?
2) How many records satisfy
timestamp = TO_DATE('2017-07-01', 'YYYY-MM-DD')
3) How many records satisfy
timestamp >= TO_TIMESTAMP('2017-07-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') AND
timestamp < TO_TIMESTAMP('2017-07-02 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
4) Does the table have stats collected? Does the timestamp column has histogram statistics?
5) Do you have an index on the timestamp column? Or it might be (sub)partitioned by timestamp?
It might be easier just send DDLs for both table and index - it will be really helpful.
Assuming you have timestamp column indexed, for the first query you're looking up by one value, in another case it is a range of value. So depending on stats and many other factors some of which are mentioned above, Oracle can choose to switch to full table scan for example, if it thinks that the second predicate returns much more rows so that its less expensive to read table directly.
I know it might be more questions than answers, but Oracle Database is very flexible and with flexibility comes complexity. Hope some of the above information will be helpful.
Also, a simple explain plan, sqlplus autrotrace or best case a 10053 trace or a 10046 trace can show a more definitive answere what's going on there.

ORACLE 11g SQL date query not returning data for today

I have the following SQL which should return all data up to 6.30am tomorrow. It has been working correctly until today (30/6/2016).
SELECT TO_CHAR(TRUK.THEDATE,'DD/MM/YY HH24:MI') DAT
FROM TRUK
WHERE TO_CHAR(TRUK.THEDATE,'DD/MM/YY HH24:MI') <= TO_CHAR(TO_DATE(sysdate + 1) + 6.5/24,'DD/MM/YY HH24:MI')
ORDER BY TRUK.THEDATE
PROBLEM
Today the data returned does not include data for 30th June,which i know exists but only 1st July. When i comment out the where clause, then all data is returned but of course this includes data AFTER 6.30am for the next day which i don't want returned.
I have searched in vain for an answer and would greatly appreciate some assistance with this. How Could the where clause be written differently to prevent this?
My desired result is that all records in the database are returned up to 6.30am the following day.
cheers
You're comparing strings, but you should be comparing dates.
Adjust your where clause to this and it'll work:
WHERE truk.thedate <= trunc(sysdate) + to_dsinterval('1 06:30:00')

Flashback query getting 'snapshot too old'

I have following query
SELECT * FROM tabis_nov_events
AS OF TIMESTAMP
TO_TIMESTAMP('2014-08-19 10:30:00', 'YYYY-MM-DD HH:MI:SS')
Which selects the data but at some point gives error "snapshot too old. rollback segment number 5 with name '_SYSSMU5$' ". I want to retrieve data if possible otherwise just leave it. I tried with where clause like below to recover by chunk of primary key but gives me error every time when I use where clause like this:
SELECT * FROM tabis_nov_events
AS OF TIMESTAMP
TO_TIMESTAMP('2014-08-19 10:30:00', 'YYYY-MM-DD HH:MI:SS')
WHERE ta_eve_violation_num<'101100010'
Is there any way to achieve this?

Getting all data between certain date time

I am reading data from remote oracle database with read only access. and I want to query all data between some time frame. I actually wanted to query between mid-night and current time. so the query I was using :
TO_DATE(to_char(sysdate, 'MM-dd-yyyy')||'00:00:00','MM-dd-yyyy HH24:MI:SS' )
AND
TO_DATE(to_char(sysdate, 'MM-dd-yyyy HH24:MI:SS'),'MM-dd-yyyy HH24:MI:SS' )
But the query
select TO_DATE(to_char(sysdate, 'MM-dd-yyyy HH24:MI:SS'),'MM-dd-yyyy HH24:MI:SS' ) from dual
is returning only 18-APR-12 not the time. How do I get time too?
I am running :
ALTER SESSION SET NLS_DATE_FORMAT='DD-MON-YYYY HH24:MI:SS';
But I don't want to run this everytime any other way to overcome this problem?
What you see is not what is really there.
Oracle holds the date as a number represanting the date and the way you see it when you query it depends on your NLS parameters.
The fact that you don't see the time doesn't mean there is no time.
as for your query I'd do something like this:
... BETWEEN trunc(sysdate) AND sysdate
I see no use in casting a Date to a string and then back to a Date with the same format ...

Oracle date corruption during update

I'm migrating some data from one oracle schema/table to a new schema/table on the same database.
The migration script does the following:
create table newtable as select
...
cast(ACTIVITYDATE as date) as ACTIVITY_DATE,
...
FROM oldtable where ACTIVITYDATE > sysdate - 1000;
If I look at the original data, it looks fine - here's one record:
select
activitydate,
to_char(activitydate, 'MON DD,YYYY'),
to_char(activitydate, 'DD-MON-YYYY HH24:MI:SS'),
dump(activitydate),
length(activitydate)
from orginaltable where oldpk = 1067514
Result:
18-NOV-10 NOV 18,2010 18-NOV-2010 12:59:15 Typ=12 Len=7: 120,110,11,18,13,60,16
The migrated data, showing that the data is corrupt:
select
activity_date,
to_char(activity_date, 'MON DD,YYYY'),
to_char(activity_date, 'DD-MON-YYYY HH24:MI:SS'),
dump(activity_date),
length(activity_date)
from newtable
where id = 1067514
Result:
18-NOV-10 000 00,0000 00-000-0000 00:00:00 Typ=12 Len=7: 120,110,11,18,13,0,16
Around 5000 out of 350k records show this problem.
Can anyone explain how this happened?
UPDATE:
I don't find any published reference to this specific type of DATE corruption on the Oracle support site. (It may be there, my quick searches just didn't turn it up.)
Baddate Script To Check Database For Corrupt dates [ID 95402.1]
Bug 2790435 - Serial INSERT with parallel SELECT and type conversion can insert corrupt data [ID 2790435.8]
The output from the DUMP() function is showing the date value is indeed invalid:
Typ=12 Len=7: 120,110,11,18,13,0,16
We expect that the minutes byte should be a value between one and sixty, not zero.
The 7 bytes of a DATE value represent, in order, century(+100), year(+100), month, day, hour(+1), minutes(+1), seconds(+1).
The only time I have seen invalid DATE values like this when a DATE value was being supplied as a bind variable, from a Pro*C program (where the bind value is supplied in the internal 7 byte representation, entirely bypassing the normal validation routines that catch invalid dates e.g. Feb 30)
There is no reason to expect the behavior you're seeing, given the Oracle syntax you posted.
This is either a spurious anomaly (memory corruption?) or if this is repeatable, then it's a flaw (bug) in the Oracle code. If it's a flaw in the Oracle code, the most likely suspects would be "newish" features in an un-patched release.
(I know CAST is a standard SQL function that's been around for ages in other databases. I guess I'm old school, and have never introduced it into my Oracle-syntax repertoire. I don't know what version of Oracle it was that introduced the CAST, but I would have stayed away from it in the first release it appeared in.)
The big 'red flag' (that another commenter noted) is that CAST( datecol AS DATE).
You would expect the optimizer to treat that as equivalent to date_col ... but past experience shows us that TO_NUMBER( number_col ) is actually interpreted by the optimizer as TO_NUMBER( TO_CHAR ( number_col ) ).
I suspect something similar might be going on with that unneeded CAST.
Based on that one record you showed, I suspect the issue is with values with a "59" value for minutes or seconds, and possibly a "23" value for hours, would be the ones that show the error.
I would try checking for places where the minutes, hour or seconds are stored as 0:
SELECT id, DUMP(activitydate)
FROM newtable
WHERE DUMP(activitydate) LIKE '%,0,%'
OR DUMP(activitydate) LIKE '%,0'
I've seen similar things to spence7593, again with Pro*C.
It is possible to create invalid dates programmatically using a DBMS_STATS package.
Not sure if there is a similar mechanism to reverse that.
create or replace function stats_raw_to_date (p_in raw) return date is
v_date date;
v_char varchar2(25);
begin
dbms_stats.CONVERT_RAW_VALUE(p_in, v_date);
return v_date;
exception
when others then return null;
end;
/
select stats_raw_to_date(utl_raw.cast_to_raw(
chr(120)||chr(110)||chr(11)||chr(18)||chr(13)||chr(0)||chr(16)))
from dual;

Resources