How to get an hourly output for 24 hours oracle - sql

Hi everyone im very very new to messing with oracle but I have to figure out how to somehow loop a query to get an hourly output on a 24 hour interval. I dont know how to declare that the time should start whenever SYSDATE is and then to add hour hour each to that.
For example something like:
Declare the system time here
Add an hour for the start time until 24 hours is complete. Do i use loop while for that so it automatically generates without having to put in new query everyday?

Not sure what are you expecting, but here is sql that will give you 24 hours (records) starting with the hour of Sysdate. You can use it as a cursor to loop through or something else....
Select
To_Char(SYSDATE, 'hh24') "HOUR_START",
CASE
WHEN To_Number(To_Char(SYSDATE, 'hh24')) + LEVEL-1 > '23' THEN
LPAD(To_Number(To_Char(SYSDATE, 'hh24')) + LEVEL-1 - 24, 2, '0')
ELSE
LPAD(To_Number(To_Char(SYSDATE, 'hh24')) + LEVEL-1, 2, '0')
END "HOURS_24"
From
Dual
CONNECT BY LEVEL <= 24

No need to use a loop or a cursor within a PL/SQL block, but using a clean SELECT statement containing XML techniques such as
SELECT TO_NUMBER(TO_CHAR(sysdate, 'hh24')) AS hour_start,
XMLCast(column_value AS INT) AS hours
FROM XMLTable('1 to 24')
ORDER BY CASE WHEN SIGN(hours-hour_start)>=0 THEN hours ELSE hours+24 END
Demo

Related

Error: an INTO clause is expected in this SELECT statement

I'm going to write a if statement within that if condition pass need to run first select statement else second one. But it showing an INTO clause is expected in this SELECT statement
declare
x integer;
begin
select to_char(sysdate,'hh') into x from dual;
if x > 12 then
select sysdate from dual;
else
select sysdate+1 from dual;
end if;
end;
You are running all three queries in a PL/SQL context (within an anonymous PL/SQL block, between the begin and end), so they all need to follow the PL/SQL rules.
That means they all need to be selected into something (or treated as cursors), so you need a date variable to select into, and then you need to do something with that variable:
declare
x integer;
d date;
begin
select to_number(to_char(sysdate, 'hh24')) into x from dual;
if x > 12 then
select sysdate into d from dual;
else
select sysdate+1 into d from dual;
end if;
-- do something with the variable
dbms_output.put_line(to_char(d, 'YYYY-MM-DD HH24:MI:SS'));
end;
/
Notice that I've also changed the first query to use the hh24 format element, because hh gives the 12-hour-clock time, which can never be more than 12.
You don't really need the first query, you can just do:
declare
d date;
begin
if to_number(to_char(sysdate, 'hh24')) > 12 then
select sysdate into d from dual;
...
But it looks like you're only using PL/SQL so you can use the if/then/else construct, which isn't available in plain SQL. That does have case though, so as #jarlh said you can do:
select
case
when to_number(to_char(sysdate,'hh24')) > 12
then sysdate
else sysdate + 1
end as result
from dual;
or
select
case
when extract(hour from systimestamp) > 12
...
You are also retaining the current system time, even if you change the date to tomorrow; you might want to set the time to midnight, which you can do with trunc(sysdate). It's unclear which you want though.
The logic also looks odd, but again it's unclear what you intended; 00-12 is modified to tomorrow and 13-23 kept as today, which might be backwards. If you want any time after (and including?) midday to be treated as tomorrow then you should be adding a day if the hour is 12 or above, so 00-11 is kept as today and 12-23 is modified to tomorrow. If that is what you meant then you can do:
select case
when extract(hour from systimestamp) >= 12
then trunc(sysdate) + 1
else trunc(sysdate)
end as result
from dual;
Or even more simply, assuming you don't want to preserve the actual time this is run, you can do:
select trunc(sysdate + 12/24) as result
from dual;
fiddle

Convert minutes to Hours:Minutes in Oracle SQL

Morning Team,
I have an Oracle SQL script that is calculating from creation of an event and how many minutes old compared to the systimestamp.
I need to convert the minutes, which are coming out as 120 for 2 hour for example, into Hours:Minutes version, i.e. 2:00
I'm struggling with that part and would like to ask if someone could help? My current code for the calculation is:
(ROUND(((cast(systimestamp as date) - cast(n.createdttm as date)))*1440,0)) "Minutes old",
I'm sure it's something simple but with all my fiddling I am not able to get it.
Thank you
You can create an INTERVAL form the minutes.
select numtodsinterval(120, 'minute') from dual
Or create a datetime from the minutes and convert its time part to a string of hours and minutes.
select to_char(trunc(sysdate) + interval '1' minute * 120, 'hh24:mi') from dual
It looks like createdttm is a timestamp, so you can just subtract:
systimestamp - createdtm
... to get an interval value like +000000000 02:00:00.00000. You can't format that directly, but you can either extract the various elements and concatenate those back together, or treat it as a string and cut out the bits you want.
If you only want the time part and it will always be less than a day you can just do:
substr(systimestamp - createdtm, 12, 5)
02:00
But if it can go over 24 hours then you probably want the day part too, which you could still get just with substr (and maybe replace to change the space to another colon) if you know it can never be more than 2 days:
substr(systimestamp - createdtm, 10, 7)
0 02:00
That's unlikely to be a safe assumption though, so instead you could extract the number of days and concatenate that:
extract(day from (systimestamp - createdtm)) || ':' || substr(systimestamp - createdtm, 12, 5)
0:02:00
You could only show the number of days if it's non-zero, but that would probably be quite confusing to who/whatever is looking at the results; but if you really wanted to:
case when extract(day from (systimestamp - createdtm)) > 0
then extract(day from (systimestamp - createdtm)) || ':'
end || substr(systimestamp - createdtm, 12, 5)
02:00
db<>fiddle with a few sample values.
One thing to note is this effectively truncates the seconds off the time; your original attempt included round(), but that might not have been what you meant.
If u want to convert minutes to hours and minutes.
If x is the number of minutes (such as 350):
TO_CHAR ( FLOOR (x / 60)) || ':'
|| TO_CHAR ( MOD (x, 60)
, 'FM00'
)
If u want to convert hours and minutes to minutes.
SELECT (TRUNC (x) * 60) +
( (MOD (x, 1)
* 100
)
FROM dual;
where x is a NUMBER. If you have a sting, s, instead, use TO_NUMBER (s) in place of x.

Select a specific time in DB2 from the currenttime

I am trying to do a select and set the time to 10AM in DB2. Ive tried
SELECT (trunc(sysdate) + 10/24) FROM sysibm.sysdummy1;
however this sets the time to 0:00:00, im trying to get it set to 10AM, is there a way to do this in DB2?
Please can you try this:
SELECT trunc(sysdate) + 10 hours FROM sysibm.sysdummy1;
Here is the DEMO
Also, in your question example you have one open bracket too many.
it should be: SELECT (trunc(sysdate) + 10/24) FROM sysibm.sysdummy1
Cheers!
Try below query.
SELECT DateAdd(Hour, 10, sysdate) FROM sysibm.sysdummy1;

Date difference get different results from function than from select statement

I need to get the difference of 2 date fields, if the greater date is null then I'll use SYSDATE instead. Having this requirement, I created a function to solve this issues (note: this code follows the standard of the organization, not my personal taste)
CREATE FUNCTION F_GET_DIFFERENCE (P_WORKFLOWID NUMBER)
RETURN NUMBER --result in minutes
IS
TIME NUMBER;
BEGIN
TIME := 0
SELECT
F_WORKTIME_DIFF(NVL(X.ENDDATE, SYSDATE), X.STARTDATE)
INTO
TIME
FROM
TABLEX X
WHERE
X.WORKFLOWID = P_WORKFLOWID;
RETURN TIME;
EXCEPTION
WHEN OTHERS THEN
RETURN 0;
END;
The F_WORKTIME_DIFF function already exists and calculates the worktime of the day (assumming nobody works at 12 a.m. and things like that). The problem is when calling this function, the result contains an additional amount of time. That's very strange, because when executing the query in the function, it returns the expected output.
Example (important: date format in Peru is DD/MM/YYYY HH24:MI:SS)
TABLEX
WORKFLOWID STARTDATE ENDDATE
1 '01/12/2012 10:00:00' null
Assumming that the server day is the same day (01/12/2012) but greater time (10:01:00), we execute the function:
SELECT F_GET_DIFFERENCE(1)
FROM DUAL;
The result is: 14.
Now, executing the query in the function and having the server time at 10:02:00, the result is 2 (exact output).
I even tried executing this
SELECT
F_WORKTIME_DIFF(NVL(X.ENDDATE, SYSDATE), X.STARTDATE) SELECT_WAY,
F_GET_DIFFERENCE(1) FUNCTION_WAY
FROM
TABLEX X
WHERE
X.WORKFLOWID = 1
And the result is (having the server time at 10:10:00)
SELECT_WAY FUNCTION_WAY
10 24
Is maybe any consideration that I must take into account when working with Oracle dates in inner functions or anything that could explain this odd behavior?
It is difficult to tell anything without seeing the function F_WORKTIME_DIFF.
Whatever is the datatype returned from F_WORKTIME_DIFF, it is casted to number when assigned to the variable time. This may be a clue.
This may not be exactly what are you looking for but the first example gives you hours diff between two dates:
Select EXTRACT(HOUR FROM (SYSDATE - trunc(SYSDATE )) DAY TO SECOND ) From dual
/
Select
EXTRACT(hour From Cast(SYSDATE as timestamp)) hh,
EXTRACT(minute From Cast(SYSDATE as timestamp)) mi,
EXTRACT(second From Cast(SYSDATE as timestamp)) ss
From dual
/

Optimizing SQL Query and Dynamically using current date

I am trying to optimize a simple SQL query and was wondering if anyone has any suggestions. I am developing using Oracle SQL Developer (which I don't like) on an Oracle 11g database. The query I am using is:
SELECT count(*)
FROM my_table
WHERE my_date
BETWEEN TO_DATE('2012-5-09T05.00.00','YYYY-MM-DD"T"HH24:MI:SS')
AND TO_DATE('2012-5-10T04.59.59','YYYY-MM-DD"T"HH24:MI:SS')
AND my_code='33'
GROUP BY my_code;
Also, I want to be able to use this query dynamically by changing the part of the date to be whatever the current date is, but I want to be able to specify the hour. So I want to be comparing something like:
getdate() + 'T05.00.00'
I have no idea how to do this and the getdate() function doesn't seem to work in SQL Developer/I don't know how to use it correctly.
So what I'm looking for is optimization suggestions and pointers on how to just dynamically change the day-month-year part of the date I want to constrain my results to. Thanks!
To get current date, you can use SYSDATE. To add x number of hours to it, you can add x/24. So something like this:
Example: Get current date + 5 hours
SELECT SYSDATE + 5/24 FROM dual
So in your example:
SELECT count(*)
FROM my_table
WHERE my_date
BETWEEN sysdate
AND sysdate + 5/24 -- if you want 5 hours ahead, for example
AND my_code='33'
GROUP BY my_code;
If you want to be able to change the number of hours, you could make this code into a function, and pass in the hours and code as variables.
Something like this:
CREATE FUNCTION myfunc
(
p_num_hours INT
, p_my_code VARCHAR
) RETURN INT
AS
l_ret INT;
BEGIN
SELECT count(*)
INTO l_ret
FROM my_table
WHERE my_date
BETWEEN sysdate
AND sysdate + p_num_hours/24
AND my_code=p_my_code
RETURN l_ret;
END;
As an alternative to adding fractional days via expressions such as "5 / 24" you might want to use an INTERVAL constant. For example:
SELECT count(*)
FROM my_table
WHERE my_date BETWEEN (TRUNC(SYSDATE) + INTERVAL '5' HOUR)
AND (TRUNC(SYSDATE) + INTERVAL '1' DAY +
INTERVAL '5' HOUR - INTERVAL '1' SECOND) AND
my_code='33'
GROUP BY my_code
I like to use INTERVAL constants because it's quite clear what these constants represent. With the fractional-day constants I sometimes get confused ('course, I sometimes get confused, regardless... :-)
Share and enjoy.
If I understand correctly, something like
select count(*)
from my_table
where trunc(my_date) = trunc(sysdate)
and my_code = '33'
group by my_code;
or
select count(*)
from my_table
where my_date
between sysdate and sysdate + 5/24
and my_code = '33'
group by my_code;
HTH.
Alessandro