Converting Integer into time - oracle

I am using Oracle 12c version.
I have a column which is integer data type and it represents total minutes.
I need to convert it into HOURS:MINUTES format.
Could someone suggest how to do that?
Thanks,
Venu

This is a fairly easy thing to accomplish using a series of built in functions.
to_char(floor(field / 60) || ':' || to_char(mod(field, 60), 'FM00')
Breaking it down:
Get the number of hours: to_char(floor(field / 60)
field / 60 gets us the number of hours
floor() ensures that we don't have to deal with decimals
to_char() converts it to a string so we can concatenate it.
Add the ':' || ':' ||
Get the number of minutes
mod(field, 60) gets the remainder of field / 60
to_char() again converts to a string for the concat step
'FM00' ensures that we keep our leading zeros.
Obviously, you'll need to replace field with whatever the field in your database is called.

You can use the to_date built-in function to translate the integer into a valid time.
Example
SQL> select to_char ( to_date ( '2300', 'HH24MI'), 'HH:MI AM') integer_time from dual;

Related

Difference in two dates not coming as expected in Oracle 11g

I get some data through a OSB Proxy Service and have to transform that using Xquery. Earlier the transformation was done on the database but now it is to be done on the proxy itself. So I have been given the SQL queries which were used and have to generate Xquery expressions corresponding to those.
Here is the SQL query which is supposed to find the difference between 2 dates.
SELECT ROUND((CAST(DATEATTRIBUTE2 AS DATE) -
CAST(DATEATTRIBUTE1 AS DATE) ) * 86400 ) AS result
FROM SONY_TEST_TABLE;
DATEATTRIBUTE1 and DATEATTRIBUTE2 are both of TIMESTAMP type.
As per my understanding this query first casts the TIMESTAMP to DATE so that the time part is stripped then subtracts the dates. That difference in days in multiplied with 86400 to get the duration in seconds.
However, when I take DATEATTRIBUTE2 as 23-02-17 01:17:19.399000000 AM and DATEATTRIBUTE1 as 23-02-17 01:17:18.755000000 AM the result should ideally be 0 as the dates are same and i'm ignoring the time difference but surprisingly the result comes as 1. After checking I found that the ( CAST(DATEATTRIBUTE2 AS DATE) - CAST(DATEATTRIBUTE1 AS DATE) ) part aparently does not give an integer value but a fractional one. How does this work?? o_O
Any help is appreciated. Cheers!
EDIT : So got the problem thanks to all the answers! Even after casting to DATE it still has time so the time difference is also calculated. Now how do I implement this in XQuery? See this other question.
Oracle DATE datatype is actually a datetime. So casting something as a date doesn't remove the time element. To do that we need to truncate the value:
( trunc(DATEATTRIBUTE2) - trunc(DATEATTRIBUTE1) )
you should try this to find difference by day
SELECT (trunc(DATEATTRIBUTE2) -
trunc(DATEATTRIBUTE1) ) AS result
FROM SONY_TEST_TABLE;
alternative 2
you can use extract like below:
SELECT ROUND (
EXTRACT (MINUTE FROM INTERVAL_DIFFERENCE) / (24 * 60)
+ EXTRACT (HOUR FROM INTERVAL_DIFFERENCE) / 24
+ EXTRACT (DAY FROM INTERVAL_DIFFERENCE))
FROM (SELECT ( TO_TIMESTAMP ('23-02-17 01:17:19', 'dd-mm-yy hh24:mi:ss')
- TO_TIMESTAMP ('23-02-17 01:17:17', 'dd-mm-yy hh24:mi:ss'))
INTERVAL_DIFFERENCE
FROM DUAL)

Get diff of time Oracle

I have the next idea :
SELECT TO_CHAR('14:00:00','HH24:MI:SS') - MIN(TO_CHAR(DATETIME,'HH24:MI:SS')) AS MINFECHA
FROM ARCHIVO2
WHERE DIA='LUNES';
I want to get the difference between the 2 fields that should be something like
00:46:00
Any comment will be appreciated.
You can't add/subtract dates and times when they're in character strings. To accomplish what you're trying to do you need to convert the character strings to DATE values, perform the necessary calculations, and then convert the result back to a character string:
WITH DATE_DATA AS
(SELECT DIA,
DATETIME,
TO_DATE(TO_CHAR(DATETIME, 'DD-MON-YYYY') || ' ' || '14:00:00', 'DD-MON-YYYY HH24:MI:SS') AS BASE_TIME
FROM ARCHIVO2)
SELECT DIA,
DATETIME,
BASE_TIME,
(DATETIME - BASE_TIME) * 1440 AS MINUTES_LATE
FROM DATE_DATA;
SQLFiddle here
Best of luck.

convert minutes to hh/mi/ss format in oracle query

I want to know the query which converts minutes to the format of hh/mi/ss in Oracle.I 've already seen lot of same questions from many forums but nothing helped me to get the exact result.
The query I used -Select to_char(to_date(mod(100,60),'mi'),'hh/mi/ss') from dual;
But I don't know how to get the hour value.Because mod function returns only the remainder I don't know how to take the quotient part and substitute into the hour field.
I suppose there are two ways of storing "minutes" in an Oracle database - you can either store them in a field whose datatype is INTERVAL DAY TO SECOND, or you can store them in a NUMBER. The simplest case to handle is the INTERVAL - in this case, the TO_CHAR function converts the value to a string of the form SDD HH:MM:SS.FFFFFF, where 'S' is sign ('+' or '-' as intervals can be positive or negative), DD = days, HH= hours, 'MM' = minutes, 'SS' = seconds, and 'FFFFFF' = fractions; thus, to get the HH:MI:SS all we need to do is use the SUBSTR function, as in
SUBSTR(TO_CHAR(I_VAL), 5, 8)
where I_VAL is an INTERVAL DAY TO SECOND value.
If the value to be converted is in a numeric field it gets a bit messy as we have to compute the individual field values, then subtract the previous fields as part of getting the next field. However, since the value stored is in minutes instead of seconds it's not particularly difficult:
create table TST (N_VAL NUMBER,
I_VAL INTERVAL DAY TO SECOND);
INSERT INTO TST(N_VAL, I_VAL) VALUES (666, INTERVAL '666' MINUTE);
SELECT N_VAL,
TRUNC(N_VAL/60) AS HOURS,
N_VAL-(TRUNC(N_VAL/60) * 60) AS MINUTES,
0 AS SECONDS,
TO_CHAR(I_VAL),
SUBSTR(TO_CHAR(I_VAL), 5, 8) AS HMS_FROM_INTERVAL
FROM TST;
SQLFiddle here
Best of luck.

Always display decimal at the end of the integer in oracle

I have a requirement where i always need to display the number with the decimal point.
The datatype of the db column is that of number.
If the value is 1.25 it gets displayed as 1.25
But if the value is 1 it does gets displayed as 1 and I need to display the value as 1.00.
I need to perform rpad (right padding) operations once I get the result in the decimal format.
Without the decimal, the value of a whole number would be different from what is present in the database.
Example:
SELECT RPAD(ROUND(12,2), 5 ,0) AS test
FROM DUAL;
results in 12000 whereas I am expecting it to be 12.00.
Any pointers on this would help.
Thanks!
Use an appropriate to_char call. Something like
SELECT to_char( <<your number>>, '0.00' )
FROM dual;
That will return the string "1.00" when you pass in a value of 1. If you pass in a value of 0, it will return the string "0.00". If you pass in a a value of 1.25, it will return the string "1.25".
Try using a number format along with the TO_CHAR function, as:
SELECT TO_CHAR(12, 99.99) AS test
FROM DUAL;
Reference:
You can find documentatation related to other ways to format numbers here.
Try this:
select TRIM(to_char(100.5, '99999999.00')) FROM DUAL
The format specifications are here:
http://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements004.htm#i34570

In Oracle, is there a function that calculates the difference between two Dates?

In Oracle, is there a function that calculates the difference between two Dates? If not, is a way to display the difference between two dates in hours and minutes?
Query:
SELECT Round(max((EndDate - StartDate ) * 24), 2) as MaximumScheduleTime,
Round(min((EndDate - StartDate) * 24), 2) as MinimumScheduleTime,
Round(avg((EndDate - StartDate) * 24), 2) as AveragegScheduleTime
FROM table1
You can subtract two dates in Oracle. The result is a FLOAT which represents the number of days between the two dates. You can do simple arithmetic on the fractional part to calculate the hours, minutes and seconds.
Here's an example:
SELECT TO_DATE('2000/01/02:12:00:00PM', 'yyyy/mm/dd:hh:mi:ssam')-TO_DATE('2000/01/01:12:00:00AM', 'yyyy/mm/dd:hh:mi:ssam') DAYS FROM DUAL
Results in: 1.5
You can use these functions :
1) EXTRACT(element FROM temporal_value)
2) NUMTOYMINTERVAL (n, unit)
3) NUMTODSINTERVAL (n, unit).
For example :
SELECT EXTRACT(DAY FROM NUMTODSINTERVAL(end_time - start_time, 'DAY'))
|| ' days ' ||
EXTRACT(HOUR FROM NUMTODSINTERVAL(end_time - start_time, 'DAY'))
||':'||
EXTRACT(MINUTE FROM NUMTODSINTERVAL(end_time - start_time, 'DAY'))
||':'||
EXTRACT(SECOND FROM NUMTODSINTERVAL(end_time - start_time, 'DAY'))
"Lead Time"
FROM table;
With Oracle Dates, this is pretty
trivial, you can get either TOTAL
(days, hours, minutes, seconds)
between 2 dates simply by subtracting
them or with a little mod'ing you can
get Days/Hours/Minutes/Seconds
between.
http://asktom.oracle.com/tkyte/Misc/DateDiff.html
Also, from the above link:
If you really want 'datediff' in your
database, you can just do something
like this:
SQL> create or replace function datediff( p_what in varchar2,
2 p_d1 in date,
3 p_d2 in date ) return number
4 as
5 l_result number;
6 begin
7 select (p_d2-p_d1) *
8 decode( upper(p_what),
9 'SS', 24*60*60, 'MI', 24*60, 'HH', 24, NULL )
10 into l_result from dual;
11
11 return l_result;
12 end;
13 /
Function created
Q: In Oracle, is there a function that calculates the difference between two Dates?
Just subtract one date expression from another to get the difference expressed as a number of days. The integer portion is the number of whole days, the fractional portion is the fraction of a day. Simple arithmetic after that, multiply by 24 to get hours.
Q: If not, is a way to display the difference between two dates in hours and minutes?
It's just a matter of expressing the duration as whole hours and remainder minutes.
We can go "old school" to get durations in hhhh:mi format using a combination of simple builtin functions:
SELECT decode(sign(t.maxst),-1,'-','')||to_char(floor(abs(t.maxst)/60))||
decode(t.maxst,null,'',':')||to_char(mod(abs(t.maxst),60),'FM00')
as MaximumScheduleTime
, decode(sign(t.minst),-1,'-','')||to_char(floor(abs(t.minst)/60))||
decode(t.minst,null,'',':')||to_char(mod(abs(t.minst),60),'FM00')
as MinimumScheduleTime
, decode(sign(t.avgst),-1,'-','')||to_char(floor(abs(t.avgst)/60))
decode(t.avgst,null,'',':')||to_char(mod(abs(t.avgst),60),'FM00')
as AverageScheduleTime
FROM (
SELECT round(max((EndDate - StartDate) *1440),0) as maxst
, round(min((EndDate - StartDate) *1440),0) as minst
, round(avg((EndDate - StartDate) *1440),0) as avgst
FROM table1
) t
Yeah, it's fugly, but it's pretty fast. Here's a simpler case, that shows better what's going on:
select dur as "minutes"
, abs(dur) as "unsigned_minutes"
, floor(abs(dur)/60) as "unsigned_whole_hours"
, to_char(floor(abs(dur)/60)) as "hhhh"
, mod(abs(dur),60) as "unsigned_remainder_minutes"
, to_char(mod(abs(dur),60),'FM00') as "mi"
, decode(sign(dur),-1,'-','') as "leading_sign"
, decode(dur,null,'',':') as "colon_separator"
from (select round(( date_expr1 - date_expr2 )*24*60,0) as dur
from ...
)
(replace date_expr1 and date_expr2 with date expressions)
let's unpack this
date_expr1 - date_expr2 returns difference in number of days
multiply by 1440 (24*60) to get duration in minutes
round (or floor) to resolve fractional minutes into integer minutes
divide by 60, integer quotient is hours, remainder is minutes
abs function to get absolute value (change negative values to positive)
to_char format model FM00 give two digits (leading zeros)
use decode function to format a negative sign and a colon (if needed)
The SQL statement could be made less ugly using a PL/SQL function, one that takes two DATE arguments a duration in (fractional) days and returns formatted hhhh:mi
(untested)
create function hhhhmi(an_dur in number)
return varchar2 deterministic
is
begin
if an_dur is null then
return null;
end if;
return decode(sign(an_dur),-1,'-','')
|| to_char(floor(abs(an_dur)*24))
||':'||to_char(mod((abs(an_dur)*1440),60),'FM00');
end;
With the function defined:
SELECT hhhhmi(max(EndDate - StartDate)) as MaximumScheduleTime
, hhhhmi(min(EndDate - StartDate)) as MinimumScheduleTime
, hhhhmi(avg(EndDate - StartDate)) as AverageScheduleTime
FROM table1
You can use the months_between function to convert dates to the difference in years and then use between the decimal years you are interested:
CASE
WHEN ( ( MONTHS_BETWEEN( TO_DATE(date1, 'YYYYMMDD'),
TO_DATE(date1,'YYYYMMDD'))/12
)
BETWEEN Age1DecimalInYears AND Age2DecimalInYears
)
THEN 'It is between the two dates'
ELSE 'It is not between the two dates'
END;
You may need to change date format to match the a given date format and verify that 31 day months work for your specific scenarios.
References:
( found on www on 05/15/2015 )
1. Oracle/PLSQL: MONTHS_BETWEEN Function
2. Oracle Help Center - MONTHS_BETWEEN

Resources