Want to round the data - oracle

My Query is :
SELECT TO_CHAR((to_date('01-01-2018 00:00:00','DD-MM-YYYY HH24:MI:SS')+ (level-1)),'DD-MM-YYYY'),
TO_CHAR(to_date('01-01-2018 00:00:00','DD-MM-YYYY HH24:MI:SS') + level,'DD-MM-YYYY') ,
to_number(regexp_substr('7000 T', '^\d+'))/(TO_DATE('04-01-2018 00:00:00', 'DD-MM-YYYY HH24:MI:SS') - TO_DATE('01-01-2018 00:00', 'DD-MM-YYYY HH24:MI:SS'))
|| regexp_substr('7000 T', '[A-Z]') AS IP_PLAN
FROM dual
CONNECT BY level <= to_date('04-01-2018 00:00:00','DD-MM-YYYY HH24:MI:SS')-to_date('01-01-2018 00:00:00','DD-MM-YYYY HH24:MI:SS');
I want IP_PLAN like: 2333 T

ROUND(('7000 T'), '[A-Z]') is trying to round a string value, i.e. the T that is extracted from that source string, which doesn't make sense.
You need to round the number you generated just before that:
select to_char(to_date('01-01-2018 00:00:00', 'DD-MM-YYYY HH24:MI:SS') + level - 1,
'DD-MM-YYYY'),
to_char(to_date('01-01-2018 00:00:00', 'DD-MM-YYYY HH24:MI:SS') + level,
'DD-MM-YYYY') ,
round(
to_number(regexp_substr('7000 T', '^[[:digit:]]+'))
/ (to_date('04-01-2018 00:00:00', 'DD-MM-YYYY HH24:MI:SS')
- to_date('01-01-2018 00:00', 'DD-MM-YYYY HH24:MI:SS'))
)
|| regexp_substr('7000 T', '[^[:digit:]]*$') as ip_plan_consumption
from dual
connect by level <= to_date('04-01-2018 00:00:00', 'DD-MM-YYYY HH24:MI:SS')
- to_date('01-01-2018 00:00:00', 'DD-MM-YYYY HH24:MI:SS');
TO_CHAR(TO TO_CHAR(TO IP_PLAN_CONSUMPTION
---------- ---------- ------------------------------------------
01-01-2018 02-01-2018 2333 T
02-01-2018 03-01-2018 2333 T
03-01-2018 04-01-2018 2333 T
so you're doing
round(<number extracted by regex> / <difference in days >)
which is
round(7000 / 3) => round(2333.333...) => 2333
and then appending the T after wards.
I've changed the regex patterns slightly so it picks up the space ans any characters at the end. That's making some assumptions about possible values in that string though - i.e. that it's always one number followed by one non-numeric section.
Incidentally, if you're using fixed dates then it's simpler to use date literals:
select to_char(date '2018-01-01' + level - 1, 'DD-MM-YYYY'),
to_char(date '2018-01-01' + level, 'DD-MM-YYYY') ,
round(
to_number(regexp_substr('7000 T', '^[[:digit:]]+'))
/ (date '2018-01-04' - date '2018-01-01')
)
|| regexp_substr('7000 T', '[^[:digit:]]*$') as ip_plan_consumption
from dual
connect by level <= date '2018-01-04' - date '2018-01-01';
though I imagine the 7000 T and the date values are all being passed in as string in your real code so they need to be converted. You could use a CTE to only convert them once though, instead of repeatedly as you loop round.

SELECT TO_CHAR((to_date('01-01-2018 00:00:00','DD-MM-YYYY HH24:MI:SS')+ (level-1)),'DD-MM-YYYY'),
TO_CHAR(to_date('01-01-2018 00:00:00','DD-MM-YYYY HH24:MI:SS') + level,'DD-MM-YYYY') ,
round(to_number(regexp_substr('7000 T', '^\d+'))/(TO_DATE('04-01-2018 00:00:00', 'DD-MM-YYYY HH24:MI:SS') - TO_DATE('01-01-2018 00:00', 'DD-MM-YYYY HH24:MI:SS')),0)
AS IP_PLAN_CONSUMPTION
FROM dual
CONNECT BY level <= to_date('04-01-2018 00:00:00','DD-MM-YYYY HH24:MI:SS')-to_date('01-01-2018 00:00:00','DD-MM-YYYY HH24:MI:SS');
you have to use T in some other column;

Related

date format picture ends before converting entire input string in Oracle

I have a PD_HEAT_DATA table with HEATID and HEATDEPARTURE_ACT columns. Data type of HEATDEPARTURE column is VARCHAR2 and it holds timestamps in the format 2019-07-28 23:11:11,359.
My requirement is to retrieve the records from PD_HEAT_DATA table between 6 AM of today and 6 AM of next day.
Sample Data:
HeatID HEATDEPARTURE_ACT
0001024002 2019-07-29 00:46:42,115
0001024003 2019-07-29 06:46:42,115
0001024004 2019-07-29 23:46:42,115
0001024003 2019-07-30 00:06:42,115
0001024004 2019-07-30 04:46:42,115
I have tried following code but it is not giving desired result:
select heatid, HEATDEPARTURE_ACT from hd_heat_data where to_date(HEATDEPARTURE_ACT, 'YYYY-MM-DD HH24:MI:SS') >= trunc(sysdate
-1) + 6/24 and
to_date(HEATDEPARTURE_ACT, 'YYYY-MM-DD HH24:MI:SS') < trunc(sysdate) + 6/24
I have tried following code but it is not giving desired result:
select heatid, HEATDEPARTURE_ACT from hd_heat_data where to_date(HEATDEPARTURE_ACT, 'YYYY-MM-DD HH24:MI:SS') >= trunc(sysdate
-1) + 6/24 and
to_date(HEATDEPARTURE_ACT, 'YYYY-MM-DD HH24:MI:SS') < trunc(sysdate) + 6/24
You have fractional seconds at the end of your HEATDEPARTURE_ACT strings which you need to trim off prior to converting the string to a date:
select heatid, HEATDEPARTURE_ACT
from hd_heat_data
where TO_DATE(REGEXP_SUBSTR(HEATDEPARTURE_ACT, '[^,]*'),
'YYYY-MM-DD HH24:MI:SS') BETWEEN trunc(sysdate-1) + INTERVAL '6' HOUR
AND trunc(sysdate) + INTERVAL '6' HOUR - INTERVAL '1' SECOND
dbfiddle here
(Note that I altered the dates in the fiddle data so results would be produced)
You need to change your format provided in TO_TIMESTAMP as TO_TIMESTAMP(HEATDEPARTURE_ACT, 'YYYY-MM-DD HH24:MI:SS,FF')
SELECT
HEATID,
HEATDEPARTURE_ACT
FROM
HD_HEAT_DATA
WHERE
TO_TIMESTAMP(HEATDEPARTURE_ACT, 'YYYY-MM-DD HH24:MI:SS,FF')
BETWEEN TRUNC(SYSDATE - 1) + INTERVAL '6' HOUR AND TRUNC(SYSDATE) +
INTERVAL '6' HOUR - INTERVAL '1' SECOND
See the demo of reproduction of the issue and resolution, HERE
Cheers!!

TO_DATE ISSUE IN CONVERSION

I tried to execute the below query but it's throwing me error :
SELECT TO_DATE(
TIMESTAMP '1970-01-01 00:00:00' + numtodsinterval(1511421211, 'second')
,'DD-MM-YYYY HH24:MI:SS')
FROM dual
Error : ORA-01830: date format picture ends before converting entire input string
The TO_DATE( datestring, format_model ) function takes strings as arguments.
Your query:
SELECT TO_DATE(
TIMESTAMP '1970-01-01 00:00:00' + numtodsinterval(1511421211, 'second')
,'DD-MM-YYYY HH24:MI:SS'
)
FROM dual
Is passing a TIMESTAMP and a string so Oracle has to perform an implicit conversion from TIMESTAMP to a string so your function is effectively:
SELECT TO_DATE(
TO_CHAR(
TIMESTAMP '1970-01-01 00:00:00' + numtodsinterval(1511421211, 'second'),
(
SELECT value
FROM NLS_SESSION_PARAMETERS
WHERE parameter = 'NLS_TIMESTAMP_FORMAT'
)
),
'DD-MM-YYYY HH24:MI:SS'
)
FROM dual
If the NLS_TIMESTAMP_FORMAT session paramter does not match your format model 'DD-MM-YYYY HH24:MI:SS' then an exception will be raised.
You could change the NLS_TIMESTAMP_FORMAT parameter - but this is a session parameter that is set per user and each user can change it at any time during their session so this should NOT be the solution.
Instead, you can just use a DATE literal instead of a TIMESTAMP literal:
SELECT DATE '1970-01-01' + NUMTODSINTERVAL (1511421211, 'second')
FROM DUAL
Or, if you want to use a timestamp then you can use the CAST function:
SELECT CAST(
TIMESTAMP '1970-01-01 00:00:00' + NUMTODSINTERVAL (1511421211, 'second')
AS DATE
)
FROM DUAL
Is this what you are expecting?
select to_char(DATE '1970-01-01' + NUMTODSINTERVAL (1511421211, 'second'), 'yyyy/mm/dd hh24:mi:ss') from dual;
The syntax appear somewhat incorrect to me. Try this:
SELECT TO_DATE ('1970-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
+ NUMTODSINTERVAL (1511421211, 'second')
FROM DUAL;
Edit:
As #a_horse.. said "Oracle DATE always contains a time",so if timestamp is not visible then you just need to see your NLS_DATE_FORMAT in table V$NLS_PARAMETERS. In your case its simply set to
NLS_DATE_FORMAT = 'DD-MM-YYYY';
So you need to alter the session first to get the timestamp in SQLPLUS. See below:
SQL> alter session set NLS_DATE_FORMAT = 'mm-dd-yyyy HH24:mi:ss';
Session altered.
SQL> SELECT TO_DATE ('1970-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS') + NUMTODSINTERVAL (15114212
11, 'second') FROM DUAL;
TO_DATE('1970-01-01
-------------------
11-23-2017 07:13:31

PL/SQL: TO_CHAR show format

So I have this code here:
create or replace FUNCTION calc_length(
START_TIME IN number,
FINISH_TIME IN number
) RETURN NUMBER IS
BEGIN
RETURN ( (FINISH_TIME - START_TIME ) ;
END
And I want to show the result in the format as H:mm
I tried TO_CHAR function but it accepts a strict preset formats.
Few examples - copy, paste to see the oputput:
SELECT trunc(mydate / 3600) hr
, trunc(mod(mydate, 3600) / 60) mnt
, trunc(mod(mydate, 3600) / 60 /60) sec
FROM
(
SELECT (to_date('01/02/2013 23:00:00', 'mm/dd/yyyy hh24:mi:ss') -
to_date('01/01/2013 07:00:00', 'mm/dd/yyyy hh24:mi:ss')) * 86400 mydate
FROM dual
)
/
Select hh, mi, ss From
(
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
)
/
Select start_date, end_date, time_diff,
EXTRACT(DAY FROM time_diff) days,
EXTRACT(HOUR FROM time_diff) hours,
EXTRACT(MINUTE FROM time_diff) minutes,
EXTRACT(SECOND FROM time_diff) seconds
From
(
Select start_date, end_date, end_date - start_date time_diff
From
(
Select CAST(to_date('21/02/2012 06:10:53 am', 'dd/mm/yyyy hh:mi:ss am') AS TIMESTAMP) end_date
, CAST(to_date('21/02/2012 12:05:00 am', 'dd/mm/yyyy hh:mi:ss am') AS TIMESTAMP) start_date
From dual
))
/

Oracle - How to check my date field value has time portion or not

I have a table containing a date type field and it holds few records with date value with time portion and few records only have date value without time portion. How to check which record has time portion and what not without navigating record by record?
This is what I'm using at the moment, but I want something faster:
SELECT MY_TAB.SEQ, MY_TAB.CRTE_DT,
CASE WHEN TRUNC (MY_TAB.CRTE_DT) = MY_TAB.CRTE_DT
THEN 'False' ELSE 'True' END AS "Has Time Portion"
FROM (SELECT 1 AS SEQ,
TO_DATE ('7/28/2013', 'MM/DD/YYYY') AS CRTE_DT
FROM DUAL
UNION
SELECT 2 AS SEQ,
TO_DATE ('11/07/2013 12:27:54', 'MM/DD/YYYY HH24:MI:SS') AS CRTE_DT
FROM DUAL) MY_TAB;
Nice Solution. Just one catch. If the timestamp is of 12:00 am midnight, then the result will be false.
TO_DATE ('11/07/2013 00:00:00', 'MM/DD/YYYY HH24:MI:SS') will yield to false
CREATE TABLE MY_TAB
AS
SELECT SEQ, CRTE_DT
FROM (SELECT 1 AS SEQ, TO_DATE ('7/28/2013', 'MM/DD/YYYY') AS CRTE_DT FROM DUAL
UNION
SELECT 2 AS SEQ,
TO_DATE ('11/07/2013 12:27:54', 'MM/DD/YYYY HH24:MI:SS') AS CRTE_DT FROM DUAL
UNION
SELECT 3 AS SEQ,
TO_DATE ('09/5/2013 00:00:00', 'MM/DD/YYYY HH24:MI:SS') AS CRTE_DT FROM DUAL
UNION
SELECT 4 AS SEQ, TO_DATE ('4/15/2013 00:00:01', 'MM/DD/YYYY HH24:MI:SS') AS CRTE_DT FROM DUAL
UNION
SELECT 5 AS SEQ, TO_DATE ('12/12/2012 1:01:01', 'MM/DD/YYYY HH24:MI:SS') AS CRTE_DT FROM DUAL);
SELECT MY_TAB.SEQ, MY_TAB.CRTE_DT,
CASE WHEN TRUNC (MY_TAB.CRTE_DT) = MY_TAB.CRTE_DT
THEN 'False' ELSE 'True' END AS "Has Time Portion"
FROM MY_TAB;
If you just want to check the data field contains time portion or not, you can do it by altering the session as,
SQL> ALTER SESSION SET NLS_DATE_FORMAT = 'dd/mm/yyyy';
Session altered.
SQL> SELECT SYSDATE FROM dual;
SYSDATE
----------
08/11/2013
SQL> ALTER SESSION SET NLS_DATE_FORMAT = 'dd/mm/yyyy hh24:mi:ss';
Session altered.
SQL> SELECT SYSDATE FROM dual;
SYSDATE
-------------------
08/11/2013 08:30:49

Oracle PLSQL truncate datetime to specific hours

I have an Oracle PLSQL code generating a list of datetime stamps and I would like to truncate them to the specific hours of 7am and 7pm rather than the beginning of the day.
For example:
01/03/2013 0700 becomes 01/03/2013 0700
01/03/2013 1235 becomes 01/03/2013 0700
01/03/2013 1932 becomes 01/03/2013 1900
02/03/2013 0612 becomes 01/03/2013 1900
My code is currently:
SELECT TRUNC(TRUNC(SYSDATE,'hh') + 1/24 - (ROWNUM) / 24, 'dd') as shift_date
FROM widsys.times
ORDER BY SYSDATE
Thanks
Without conditionals :)
Select your_date,
trunc(your_date - 7/24) + --the date
trunc(to_char(your_date - 7/24,'hh24')/12)/2 + --wich half of day
7/24 --shift the hour
from
your_table;
See a fiddle.
with data(time) as (
select to_date('2013-09-19 00:00:00', 'YYYY-MM-DD HH24:MI:SS') from dual union all
select to_date('2013-09-19 06:45:44', 'YYYY-MM-DD HH24:MI:SS') from dual union all
select to_date('2013-09-19 08:12:25', 'YYYY-MM-DD HH24:MI:SS') from dual union all
select to_date('2013-09-19 18:59:59', 'YYYY-MM-DD HH24:MI:SS') from dual union all
select to_date('2013-09-19 19:00:00', 'YYYY-MM-DD HH24:MI:SS') from dual union all
select to_date('2013-09-19 20:15:35', 'YYYY-MM-DD HH24:MI:SS') from dual union all
select to_date('2013-09-19 23:59:59', 'YYYY-MM-DD HH24:MI:SS') from dual
)
select d.time,
case
when to_number(to_char(d.time, 'HH24')) >= 19 then
trunc(d.time) + 19/24
when to_number(to_char(d.time, 'HH24')) >= 7 then
trunc(d.time) + 7/24
else
trunc(d.time - 1) + 19/24
end as shift_date
from data d
;
Are you looking for a query like this:
SELECT CASE
WHEN TO_CHAR(your_date, 'hh24') > 12
THEN TRUNC(your_date)+ 19/24
ELSE TRUNC(your_date)+ 7/24
END
FROM your_table;

Resources