Oracle Time Comparisons - sql

Is Oracle (10g) doing a proper TIME comparison here, or do I need to convert to decimal time and then compare? E.g.,
IF (SELECT TO_CHAR(sysdate,'HH24:MI:SS') from dual) <= '15:00'
THEN (...)
Thanks.

IF (sysdate <= trunc(sysdate)+15/24)
THEN (...)
should do the trick...

You can't do a select in an if statement, but you can do a direct comparison to sysdate. If you're doing it like this it would probably be better to use a number rather than relying on implicit conversion. You also don't need the extra minutes etc. Something like,
begin
if to_number(to_char(sysdate,'HH24')) <= 15 then
-- do something
end if;
end;
If you did want to use the minutes then by converting it into a string without the colon you can do a more direct comparison. As long as the date / time is converted in 24 hour format without extras and in reverse, year, month, day, hour etc comparisons will always be accurate, e.g.
begin
if to_char(sysdate,'HH24MI') <= '1515' then
-- do something
end if;
end;
However, it's often best to do date comparisons as #cagcowboy has just posted before I got there!

use the following code
SELECT TO_CHAR(SYSDATE, 'HH24MI') INTO V_SYS_TIME FROM DUAL;
IF V_SYS_TIME BETWEEN V1_TIME AND V2_TIME THEN
(....)

Related

Can I add this format in sqlite3

I have a columns called time_spent and it is like: hh:mm:ss. For example, 00:23:11, this means it is 23 minutes and 11 seconds. I wonder how I can add up a multiple of these. Say like 00:23:11 + 00:10:20 = 00:33:31. I am not sure how to directly do that in commands. I have tried convert and CAST, but they ended up failed. Any help would be appreciated.
You can turn your times to seconds using time_to_sec(), sum them, and then turn the result to a time using sec_to_time().
As an example, the following query would compute the total time_spent over the whole table:
select sec_to_time(sum(time_to_sec(time_spent))) total_time_spent
from mytable
This will work even it your times are stored as string, since their format complies to MySQL format for the time datatype.
Note that MySQL time datatype can handle values between '-838:59:59' to '838:59:59' only. If your total time is greater than that, then you will not be able to convert it back to a time.
Once you store dates in DATE, TIME and DATETIME formats there are a multitude of available date and time functions you can use.
You can do it with the function time():
select time('00:23:11', '+00:10:20')
or just:
select time('00:23:11', '00:10:20')
Result:
00:33:31
If the sum may exceed 24 hours, for example when you want to add '23:59:59' to '00:23:11' then use this statement:
select
case
when strftime('%d', datetime('00:23:11', '23:59:59')) = '01' then time('00:23:11', '23:59:59')
else (24 + time('00:23:11', '23:59:59')) || strftime(':%M:%S', time('00:23:11', '23:59:59'))
end
Or:
select
(24 * (strftime('%d', datetime('00:23:11', '23:59:59')) - 1) + time('00:23:11', '23:59:59')) ||
strftime(':%M:%S', time('00:23:11', '23:59:59'))
Result:
24:23:10

Retirement Date Function in Oracle SQL

Please I want to calculate the retirement of an employee from his Date of First Appointment using a function before retrieving the result using a trigger and store it in the Retirement date column: but I am not good with the syntax please can someone help:... Below is my code for the function
CREATE OR REPLACE Function EDOR_DATE
(DOFA IN date)
RETURN date
IS
NEW_EDOR_RESULT date;
BEGIN
SELECT DOFA + ((365*35) + 9) as NEW_EDOR
FROM EMPLOYEES_MASTER_DETAILS;
fetch NEW_EDOR into NEW_EDOR_RESULT;
RETURN NEW_EDOR_RESULT;
END;
First a couple comments on the changes you indicated you made to the function:
Removing the "IN" from the declaration actually accomplishes nothing.
If you do not specify "IN', "OUT", or "IN OUT" the compiler defaults to "IN". All removing it does is a change from an explicit to implicit declaration.
Placing a semi-colon (;) where indicated will generate an error.
As for the function itself you are making it way more complicated than necessary. A simple assignment is all that's needed. Also, Boneist's suggestion of add_months is the correct function for adding years as it will adjust for leap year and number of days per month (if needed).
Thus your function reduces to:
create or replace function edor_date(dofa in date)
return date
is
l_edor_date date;
begin
l_edor_date := add_months(dofa, 35*12) ;
return l_edor_date ;
end;
or even further to just:
create or replace function edor_date (dofa in date)
return date
is
begin
return add_months(dofa, 35*12) ;
end;
BTW: I actually like the idea of using a function for this as it hides the implementation details of the business rule. However, it does impose a slight overhead for each call.
CREATE OR REPLACE Function EDOR_DATE
(DOFA date)
RETURN date
IS
NEW_EDOR_RESULT date;
BEGIN
--I am converting this to a case statement that is easier to read
select
case
when dofa - dob <= 25 then dofa + ((365*35)+9)
else dob + ((365*60)+9)
end
into new_edor_result
from employees_master_details;
return new_edor_result;
end;
This can be done without needing to use a function. Also, why are you adding numbers of days? A year is not 365 days long. You should be using the add_months() feature.
Here is how I would do this, assuming all the columns in question belong to the EMPLOYEES_MASTER_DETAILS table:
select emp_id,
dob,
hire_date,
case when months_between(hire_date, dob) <= 25 * 12 then add_months(hire_date, 35*12)
else add_months(dob, 60*12)
end retirement_date
from EMPLOYEES_MASTER_DETAILS emd;
If you need to calculate the retirement upon insert, then simply use the case expression as part of the insert statement.

SQL. Select Unixtime for whole day

I am looking for a way to select a whole days worth of data from a where statement. Timestamp is in unix time such as (1406045122). I want to select the today's date of unix time range and find all the food that has been added in today. Thank in advance. This is the code I wrote. I'm not sure what I should put in the ( ????? ) part. I know it has to do with 60*60*24=86400 secs per day but I'm not too sure how I can implement this.
Select timestamp,food from table1 where timestamp = ( ????? );
Select timestamp,food
FROM table1
WHERE timestamp > :ts
AND timestamp <= (:ts + 86400);
replace :ts with the starting timstamp and you'll filter a whole day's worth of data
edit
This select query would give you the current timestamp (there may be more efficient ones, i don't work with sqlite often)
select strftime("%s", current_timestamp);
You can find more info about them here: http://www.tutorialspoint.com/sqlite/sqlite_date_time.htm
Using the strftime() function, combined with the date() function we can write this following query which will not need any manual editing. It will return the records filtered on timestamp > start of today & timestamp <= end of today.
Select timestamp,food
FROM table1
WHERE timestamp > strftime("%s", date(current_timestamp))
AND timestamp <= (strftime("%s", date(current_timestamp)) + 86400);
Your mileage will likely depend on your version of SQL but for example on MySQL you can specify a search as being BETWEEN two dates, which is taken conventionally to mean midnight on each. So
SELECT * FROM FOO WHERE T BETWEEN '2014-07-01' AND '2014-07-02';
selects anything with a timestamp anywhere on 1st July 2014. If you want to make it readable you could even use the ADDDATE function. So you could do something like
SET #mydate = DATE(T);
SELECT * FROM FOO WHERE T BETWEEN #mydate AND ADDDATE(#mydate, 1);
The first line should truncate your timestamp to be 00:00:00. The second line should SELECT only records from that date.

Oracle convert RAW to date format

I have a RAW field in my Oracle database that represents the date of user registered in system.
The value is something like 24E2321A0000000000 However I need convert the value to the date it represents (etc 2008-12-25 15:04:31).
I tried with totimestamp (see this sqlfiddle) but that didn't work.
Maybe this will help:
SELECT utl_raw.cast_to_binary_integer('24E2321A0000000000') raw_to_int
FROM dual
/
Output is 36. I'm not sure if you need days or hours. Next example is about adding 36 hours to SYSDATE:
-- SYSDATE + 36/24 --
SELECT SYSDATE+(utl_raw.cast_to_binary_integer('24E2321A0000000000')/24) my_date
FROM dual
/
MY_DATE
---------------------
12/13/2013 4:29:22 AM
please try one
declare
d date;
begin
dbms_stats.convert_raw_value (hextoraw('7876070A010101'), d);
dbms_output.put_line (d);
end;

How to get records after a certain time using SQL datetime field

If I have a datetime field, how do I get just records created later than a certain time, ignoring the date altogether?
It's a logging table, it tells when people are connecting and doing something in our application. I want to find out how often people are on later than 5pm.
(Sorry - it is SQL Server. But this could be useful for other people for other databases)
For SQL Server:
select * from myTable where datepart(hh, myDateField) > 17
See http://msdn.microsoft.com/en-us/library/aa258265(SQL.80).aspx.
What database system are you using? Date/time functions vary widely.
For Oracle, you could say
SELECT * FROM TABLE
WHERE TO_CHAR(THE_DATE, 'HH24:MI:SS') BETWEEN '17:00:00' AND '23:59:59';
Also, you probably need to roll-over into the next day and also select times between midnight and, say, 6am.
In MySQL, this would be
where time(datetimefield) > '17:00:00'
The best thing I can think would be: don't use a DateTime field; well, you could use a lot of DATEADD/DATEPART etc, but it will be slow if you have a lot of data, as it can't really use an index here. Your DB may offer a suitable type natively - such as the TIME type in SQL Server 2008 - but you could just as easily store the time offset in minutes (for example).
For MSSQL use the CONVERT method:
DECLARE #TempDate datetime = '1/2/2016 6:28:03 AM'
SELECT
#TempDate as PassedInDate,
CASE
WHEN CONVERT(nvarchar(30), #TempDate, 108) < '06:30:00' then 'Before 6:30am'
ELSE 'On or after 6:30am'
END,
CASE
WHEN CONVERT(nvarchar(30), #TempDate, 108) >= '10:30:00' then 'On or after 10:30am'
ELSE 'Before 10:30am'
END
Another Oracle method for simple situations:
select ...
from ...
where EXTRACT(HOUR FROM my_date) >= 17
/
http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/functions050.htm#SQLRF00639
Tricky for some questions though, like all records with the time between 15:03:21 and 15:25:45. I'd also use the TO_CHAR method there.
In Informix, assuming that you use a DATETIME YEAR TO SECOND field to hold the full date, you'd write:
WHERE EXTEND(dt_column, HOUR TO SECOND) > DATETIME(17:00:00) HOUR TO SECOND
'EXTEND' can indeed contract the set of fields (as well as extend it, as the name suggests).
As Thilo noted, this is an area of extreme variability between DBMS (and Informix is certainly one of the variant ones).
Ok, I've got it.
select myfield1,
myfield2,
mydatefield
from mytable
where datename(hour, mydatefield) > 17
This will get me records with a mydatefield with a time later than 5pm.