Oracle APEX report - processing a field value - sql

I have been creating Oracle APEX reports for a while.
I need to processes a column value to charge it's format.
The current SQL looks like this. All is good.
select PP_RUNDATA.ID as ID,
PP_RUNDATA.PP_START_TIME as PP_START_TIME,
PP_RUNDATA.PP_END_TIME as PP_END_TIME,
from PP_RUNDATA PP_RUNDATA
The time columns are in seconds. This PL/SQL converts the seconds into date / time. (this work well)
alter session set nls_date_format="dd/mm/yyyy - hh24:mi:ss";
select date '1970-01-01' + 1661596871 * interval '1' second result from dual;
I need to bring together the SQL and PL/SQL and change the 1661596871 to the column value.
I know I can use a "List Value" to process the PP_START_TIME / PP_END_TIME column using PL/SQL returning SQL.
A very poor, not working example,
declare
temp1 varchar2(500);
begin
EXECUTE IMMEDIATE 'alter session set nls_date_format="dd/mm/yyyy - hh24:mi:ss"';
select date '1970-01-01' + PP_START_TIME * interval '1' second into temp1 from dual;
return 'select temp2 from dual';
End;
I know there are more than two things wrong with this coding;
1) Syntax to access data in column PP_START_TIME (maybe &PP_START_TIME.)
2) the "return statement"
What am I doing wrong in the coding / my thinking in the above or maybe the overall approach in Oracle APEX Reports?
Thanks for looking
Pete

You can use:
select ID,
DATE '1970-01-01' + PP_START_TIME * INTERVAL '1' SECOND as PP_START_TIME,
DATE '1970-01-01' + PP_END_TIME * INTERVAL '1' SECOND as PP_END_TIME
from PP_RUNDATA
If you want a particular format then you can use TO_CHAR:
select ID,
TO_CHAR(
DATE '1970-01-01' + PP_START_TIME * INTERVAL '1' SECOND,
'dd/mm/yyyy - hh24:mi:ss'
) as PP_START_TIME,
TO_CHAR(
DATE '1970-01-01' + PP_END_TIME * INTERVAL '1' SECOND,
'dd/mm/yyyy - hh24:mi:ss'
) as PP_END_TIME
from PP_RUNDATA

Related

How can i pass variable with in single quote oracle sql

select
to_char(sysdate + interval '2' hour,'hh12:mi AM') as Time
from dual
i have a query that will add 2 hours from current system time , but it may add aur subtract the time and also hour's value will also be dynamic
so i have to use operator value it may + or - and similarly hour value it may 2 ,3 ,4 or 5 so my query will be
select
to_char(sysdate :operator interval ':hourvalue' hour,'hh12:mi AM') as Time
from dual
it gives me error
ORA-00907: missing right parenthesis
please help me out i am using oracle 11g
You cannot have an INTERVAL literal of a variable amount; however, you can have a fixed INTERVAL literal and then multiply it by a bind variable:
SELECT TO_CHAR(
SYSDATE + :hourvalue * INTERVAL '1' HOUR,
'hh12:mi AM'
) AS TIME
FROM DUAL
If you want a negative amount then just specify a negative :hourvalue rather than using a separate :operator bind variable.
You can use NUMTODSINTERVAL(n, 'hour') where n can has a negative value as well.
For example
SELECT NUMTODSINTERVAL((-1)*10, 'hour') h FROM DUAL;
You can also create an interval -(1 hour 37 min 41 sec):
SELECT NUMTODSINTERVAL((-1) * (1*3600 + 37*60 + 41), 'second') hms FROM DUAL;
Note, n is a number (decimal), so this will work too:
SELECT NUMTODSINTERVAL((-1) * (1 + 37/60 + 41/3600), 'hour') hms FROM DUAL;
It's only possible to use bind variables for arguments, you cannot use operators as bind variables. A workaround is to multiply the interval by -1 for negative and 1 for positive.
SELECT
TO_CHAR(
SYSDATE + numtodsinterval((CASE WHEN :operator = '-' THEN -1 ELSE 1 END * :interval),'hour'),
'hh12:mi AM'
) as time
FROM DUAL;

Sysdate in where clause not working in oracle sql

I have below select query where i am trying to get the data only for today date but its not returning anything:
select * from V_TER
where SYSTEM_INSERTED_AT = SYSDATE;
The SYSTEM_INSERTED_DATE is of Date datatype and the value is stored in this fields as for example 2021-01-15 15:17:13
The problem in Oracle is that dates can have time components both in the data and sysdate itself.
I would recommend checking for any time on the current date:
where system_inserted_at >= trunc(sysdate) and
system_inserted_at < trunc(sysdate) + interval '1' day
This is generally optimizer-friendly. If you don't care about that, then:
where trunc(system_inserted_at) = trunc(sysdate)

Migrating Oracle query to PostgreSQL

Can you please help me with this? How can I convert below query to PostgreSQL.
The query below gives different output when executed in PostgreSQL than when executed in Oracle.
SELECT
to_char(to_date('01011970','ddmmyyyy') + 1/24/60/60 * 4304052,'dd-mon-yyyy hh24:mi:ss')
from dual;
Let's assume you want to use the same expression as in Oracle to compute the resulting value.
The reason it is not working when you simply remove from dual is because this expression is being evaluated to 0 as integer division truncates results towards 0.
select 1/24/60/60 * 4304052;
?column?
----------
0
(1 row)
If I make one of them a decimal, it will give you the required result
select 1.0/24/60/60 * 4304052;
?column?
-----------------------------
49.815416666666666347848000
Now, after changing this, your expression will return the same result you got in Oracle.
SELECT to_char( to_date('01011970','ddmmyyyy')
+ INTERVAL '1 DAY' * (1.0/24/60/60 * 4304052) ,'dd-mon-yyyy hh24:mi:ss') ;
to_char
----------------------
19-feb-1970 19:34:12
(1 row)
Note that I had to add an interval expression, because unlike Oracle, a Postgres DATE does not store time component and simply adding a number to date will result in an error. Using an interval will ensure that it will be evaluated as timestamp.
knayak=# select pg_typeof( current_date);
pg_typeof
-----------
date
(1 row)
knayak=# select pg_typeof( current_date + INTERVAl '1 DAY');
pg_typeof
-----------------------------
timestamp without time zone
(1 row)
I think you want:
select '1970-01-01'::date + 4304052 * interval '1 second';
You can use to_char() to convert this back to a string, if you really want:
select to_char('1970-01-01'::date + 4304052 * interval '1 second', 'YYYY-MM-SS HH24:MI:SS');

Using "Interval" in Oracle where "Interval" is a value from a table

I need to generate a list of values in an Oracle DB with the following columns of data:
ITEM_TYPE VARCHAR2(20)
ITEM_LAST_UPDATED DATE
ITEM_UPDATE_TOLERANCE NUMBER(1)
The only data that should be send out to the console would be items that have the date in 'ITEM_LAST_UPDATED' less than the sysdate minus the integer value within 'ITEM_UPDATE_TOLERANCE'.
So, if I wanted to just show the ones that were one hour past due, I can do:
select ITEM_TYPE from MY_TABLE
where
to_char(ITEM_LAST_UPDATED, 'DD-MON-YYYY HH24:MI')
<=
to_char(sysdate - interval '1' hour, 'DD-MON-YYYY HH24:MI');
However, rather than using the '1' in the above statement, I need to replace it with the numeric value of ITEM_UPDATE_TOLERANCE.
I tried several different versions, but all error (such as):
select ITEM_TYPE from MY_TABLE
where
to_char(ITEM_LAST_UPDATED, 'DD-MON-YYYY HH24:MI')
<=
to_char(sysdate - interval to_number(ITEM_UPDATE_TOLERANCE) hour, 'DD-MON-YYYY HH24:MI');
Why are you converting a perfect DATE column to a character value just to compare it another DATE value converted to a character column.
Simply use:
ITEM_LAST_UPDATED <= sysdate - interval '1' hour
To achieve what you want, just multiply the value:
ITEM_LAST_UPDATED <= sysdate - (interval '1' hour) * ITEM_UPDATE_TOLERANCE
There is also absolutely no need to convert a number to a number using the to_number() function.
As an alternative to #a_horse_with_no_name's interval multiplication trick, or San's division method, you can also use the numtodsinterval() function:
ITEM_LAST_UPDATED <= sysdate - numtodsinterval(ITEM_UPDATE_TOLERANCE, 'HOUR')
As an example:
select sysdate, sysdate - numtodsinterval(3, 'HOUR') from dual;
SYSDATE SYSDATE-NUMTODSINTE
------------------- -------------------
2014-03-07 19:08:27 2014-03-07 16:08:27
Well you can try using simple calculation
select ITEM_TYPE from MY_TABLE
where
ITEM_LAST_UPDATED
<=
sysdate - (ITEM_UPDATE_TOLERANCE/24);
Calculation of ITEM_UPDATE_TOLERANCE/24 will convert hours into days and then can be subtracted from sysdate.

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