Find entries in sql that were done milliseconds against each other - sql

I need to debug an issue I found with someone else's code, where it reads both the id and the timestamp for a key. But, I noticed that it is not reading the millisecond information. While this is a potential cause, this not confirmed, and I need to find out if this is the cause.
The problem could occur if two entries in the table happened within the same second, 10:20:05.0500 pm and 10:20:05.5000 pm, but not 10:20:05.5000 and 10:20:06.0500.
How do I write such a query to look for it?
I am using Oracle pl/sql.

In Oracle to use fractional seconds a column must be of data type "TIMESTAMP".
Maybe someone else's code is using a variable of type DATE, which is year-month-day hour-minute-second without fractional seconds.
Database SQL Language Reference: Data Types
Can you give the table description and someone else's code?

To find records with the same date/time up to second precision but with different milliseconds, you can compare different records by joining the table to itself
SELECT A.ts, B.ts
FROM
Test A
INNER JOIN Test B
ON TO_CHAR(A.ts, 'YYYY-MM-DD HH24:MI:SS') = TO_CHAR(B.ts, 'YYYY-MM-DD HH24:MI:SS')
WHERE
A.ts < B.ts
ORDER BY
A.ts, B.ts;
TO_CHAR truncates the milliseconds. This is important, because functions that round could yield different seconds. E.g., CAST(ts as timestamp(0)) rounds, which is not what wee need.
The example from the link below has a record with 999 milliseconds to test this.
See example on SQL Fiddle.

Related

Get information between two different times Oracle

I am making a modification to an Oracle Query, where I need to get the information found from the query date and minute up to 30 minutes ago.
For example, I made the query at 16:35, so I need it to show me the information found from 16:05 to 16:35.
I did something like this, but I don't have the result I need.
Also, how can I make it find everything loaded with current date? This is what I have done with no result
AND FV.FEC_CAR = dateadd(minute,-30,getdate()) ORDER BY F.N_FILE DESC
Thank you very much in advance
dateadd and getdate aren't valid in Oracle's SQL dialect. That looks like SQL Server syntax but it probably works in some other database as well.
In Oracle, you'd do
fv.fec_car > sysdate - interval '30' minute
or
fv.fec_car > sysdate - 30/24/60
I find the interval syntax far clearer personally
As far as I can understand and interpret, you need to see the data at a point in the past before applying some modification to your table. This case,
SELECT *
FROM tab AS OF TIMESTAMP SYSTIMESTAMP - INTERVAL '30' MINUTE
might be used to see the values of half an hour before modification if undo_retention parameter's value of your database is big enough(without forgetting that it does not guarantee to return a result even if the value is big enough)

use of trunc date in sql

can anyone explain me the working of trunc(date) function in oracle.
my query is as below.
select trunc(tran_date) from tablename;
i have not passed any format type.
If i compare the date present in table without having trunc(date) it will not give any output.
and if compare date table with trunc(date) it will give me proper ouptut.
please explain how it is working.
and is there any replacement for trunc function as it is taking too much time.
trunc(tran_date) returns the date portion of the date column with no time component (which is midnight at the start of the day).
Despite its name, the date data type in Oracle includes the time. This is even more confusing because you sometimes do not see the time in the result set (depending on how you access the data).
The dates that you are comparing to have no time component. So, the comparison works with trunc(). But the time component on tran_date prevents the comparison from working without trunc().

Understanding timestamp- 1505143211567 (Oracle DB)

I have the following timestamp "1505143211567". By removing the last 3 numbers I can able to convert to normal human readable format. The DB is running from Oracle. I want to convert this timestamp to human readable. I tried something like below.
From sql I can write it by removing last 3 and
select from_unixtime(1505143211)
But in oracle its kind of different. And each time I dont want to remove the number and check manually.
Need is : DB query.
The timestamp you are getting seems to be an EPOC value, when using an online converter I got the following:
1505143211567 -> 2017-09-11 15:20:12
I'm no expert in Oracle, however there are a lot of resources out there in converting this to a human readable format, does the following help ?
select TO_CHAR( FROM_TZ( CAST(DATE '1970-01-01' + (1/24/60/60/1000) * <column name> AS TIMESTAMP), 'Europe/London'), 'MM/DD/YYYY HH24:MI:SS') from <tablename>;
Where column name is your timestamp column, and tablename is obviously the table you are getting the column from. source can be found here.
You also have a few stackoverflow posts with the issue as well.
Here might be a good one to follow.

Parse time strings with different formats and compare them

I am running a query between several tables and I am running into an issue between comparing two time columns on separate tables: "rc1_time" is in a string format and "osemplog_time" is in a time format. both are time only with no date
rc1_time's contents look like this '10560684' which corresponds to HH24MISSMS
osemplog_time's contents look like 07:57:02.917455
how do I format the rc1_time into a "time format" with no date?
what are some options for comparing the two times?
I am newbie at this exposition on your answers would be welcome
below is my query
SELECT
"public".payroll_master.prm1_name,
"public".payroll_master.prm1_oe_init,
"public".receipt.rc1_init,
"public".employee_log.osemplog_ipaddress,
"public".employee_log.osemplog_event,
"public".receipt.rc1_date,
"public".employee_log.osemplog_logdate,
"public".receipt.rc1_code,
"public".employee_log.osemplog_logname,
"public".oslogname.lognm_empname,
"public".receipt.rc1_arname,
"public".receipt.rc1_arnum,
"public".receipt.rc1_time,
"public".employee_log.osemplog_logtime
FROM
"public".receipt
INNER JOIN "public".employee_log ON "public".receipt.rc1_date = "public".employee_log.osemplog_logdate
INNER JOIN "public".payroll_master ON "public".payroll_master.prm1_oe_init = "public".receipt.rc1_init
INNER JOIN "public".oslogname ON "public".oslogname.lognm_empname = "public".payroll_master.prm1_name AND "public".oslogname.lognm_name = "public".employee_log.osemplog_logname
WHERE
"public".receipt.rc1_code = 'CA'
AND
"public".employee_log.osemplog_logdate = "public".receipt.rc1_date
ORDER BY
"public".receipt.rc1_init ASC
Question as stated
You can represent a time without a date using the time data type. To convert a string from a given format into one, you can go through the to_timestamp function and then cast to time:
SELECT to_timestamp('10560684', 'HH24MISSUS')::time;
SELECT to_timestamp('07:57:02.917455', 'HH24:MI:SS.US')::time;
The basic idea is that you parse the time string using to_timestamp. The resulting timestamp will have a default date, and casting to time will remove the date, leaving only the parsed out time portion.
Assumptions:
Your hours are in 24-hour clock format (13-23 for 1 PM to 11 PM and 00 for midnight). If they are not 24 hour times, then you are missing the AM/PM designation and will need to sort that out.
The second "SS" you mention in your first pattern is actually a fractional part of seconds. If not, you'll need to adjust the pattern. If you don't care about the fractional seconds, you might consider just leaving the US and the .US off entirely and working only at the seconds level. Note that US interprets 84 to be 0.84 seconds, not actually 84 microseconds (0.000084 seconds).
Ultimately, you will need to either provide much more precise details about the format or figure out the correct format string yourself. Rather than worry about those details, I've tried to exemplify the general mechanism and leave those to you.
Comparison is then trivial. You just use PostgreSQL's operators (<, >, =, etc.):
SELECT to_timestamp('07:57:02.917455', 'HH24:MI:SS.US')::time < to_timestamp('10560684', 'HH24MISSUS')::time;
Other considerations
Be aware of time zone issues if you are working across them. You'll want to look at timetz (short form of time with time zone) or timestamptz (short form of timestamp with time zone) if you need to deal with time zones. Generally, I would recommend including time zone handling up front in case it becomes a problem later.
In this case, why not build a complete timestamp? You already have the dates: "public".receipt.rc1_date and "public".employee_log.osemplog_logdate.
You don't specify the data types, but whatever the forms of those are, it should be possible. For example, if they are actual date objects, then:
SELECT to_timestamp(to_char("public".receipt.rc1_date, 'YYYY-MM-DD')||' '||"public".receipt.rc1_time, 'YYYY-MM-DD HH24MISSMS');
If they are strings of the form 'YYYY-MM-DD', then:
SELECT to_timestamp("public".receipt.rc1_date||' '||"public".receipt.rc1_time, 'YYYY-MM-DD HH24MISSMS');
And so on. Now you have a real timestamp, which makes simple great/less than comparison much, much easier.
In my experience, it's extremely rare that you actually want to test time stamps with fractional second precision for equality. You might want a more tolerant equality check, something like SELECT t1 - t2 < interval '5 seconds', but this is really up to the application.

Issue querying date from oracle.

I understand that querying a date will fail as its comparing a string to date and that can cause an issue.
Oracle 11.2 G
Unicode DB
NLS_DATE_FORMAT DD-MON-RR
select * from table where Q_date='16-Mar-09';
It can be solved by
select * from table where trunc(Q_date) = TO_DATE('16-MAR-09', 'DD-MON-YY');
What I don't get is why this works.
select* from table where Q_date='07-JAN-08';
If anyone can please elaborate or correct my mindset.
Thanks
Oracle does allow date literals, but they depend on the installation (particularly the value of NLS_DATE_FORMAT as explained here). Hence, there is not a universal format for interpreting a single string as a date (unless you use the DATE keyword).
The default format is DD-MM-YY, which seems to be the format for your server. So, your statement:
where Q_date = '07-JAN-08'
is interpreted using this format.
I prefer to use the DATE keyword with the ISO standard YYYY-MM-DD format:
where Q_Date = DATE '2008-01-07'
If this gets no rows returned:
select * from table where Q_date='16-Mar-09';
but this does see data:
select * from table where trunc(Q_date) = TO_DATE('16-MAR-09', 'DD-MON-YY');
then you have rows which have a time other than midnight. At this point in the century DD-MON-RR and DD-MON-YY are equivalent, and both will see 09 as 2009, so the date part is right. But the first will only find rows where the time is midnight, while the second is stripping the time off via the trunc, meaning the dates on both sides are at midnight, and therefore equal.
And since this also finds data:
select* from table where Q_date='07-JAN-08';
... then you have rows at midnight on that date. You might also have rows with other times, so checking the count with the trunc version might be useful.
You can check the times you actually have with:
select to_char(q_date, 'YYYY-MM-DD HH24:MI:SS') from table;
If you do want to make sure you catch all times within the day you can use a range:
select * from table where
q_date >= date '2009-03-16'
and q_date < date '2009-03-17';
Quick SQL Fiddle demo.
Although it sounds like you're expecting all the times to be midnight, which might indicate a data problem.