reperesent AM or PM values with time in oracle - sql

i have a table with two date columns: time_from,time_to.Both have datatype of date.Now,I want to concatenate these column values such that I can get only times like this:
9:00 PM-9:50 PM.
Now,some of my times are in AM while others are PM and I want to write a select statement to concatenate them.I wrote this but it is not returning "AM" or "PM" correct everytime.
My query is:
select
to_char(time_from,'HH:MI:SS PM') || ' - ' || to_char(time_to,'HH:MI:SS PM')
from
table-name
I had initially inserted my time in 12 hr format.
Need some guidance here please? I don't want to hard code AM or PM

Now,some of my times are in AM while others are PM
DATE is not stored in the database the way you see it. What you see is only for display purpose for us to interpret it. Oracle stores date in an internal format of 7 bytes which is it's proprietary format.
but it is not returning "AM" or "PM" correct everytime
You need to validate your data as TO_CHAR doesn't manipulate the data. It will display the datetime in your desired format.
It only depends on the DATE value in your table, and is independent of the format model AM/PM in TO_CHAR.
-- setting nls_date_format only for the DATE value display
SQL> alter session set nls_date_format='MM/DD/YYYY HH:MI:SS PM';
Session altered.
PM format:
SQL> WITH DATA AS
2 ( SELECT SYSDATE - 4/24 from_date, SYSDATE + 4/24 to_date FROM dual
3 )
4 SELECT from_date,
5 to_date,
6 TO_CHAR(from_date, 'HH:MI PM')
7 ||' - '
8 ||TO_CHAR(to_date, 'HH:MI PM') my_tm_format
9 FROM DATA;
FROM_DATE TO_DATE MY_TM_FORMAT
---------------------- ---------------------- -------------------
11/12/2015 07:39:05 AM 11/12/2015 03:39:05 PM 07:39 AM - 03:39 PM
AM format:
SQL> WITH DATA AS
2 ( SELECT SYSDATE - 4/24 from_date, SYSDATE + 4/24 to_date FROM dual
3 )
4 SELECT from_date,
5 to_date,
6 TO_CHAR(from_date, 'HH:MI AM')
7 ||' - '
8 ||TO_CHAR(to_date, 'HH:MI AM') my_tm_format
9 FROM DATA;
FROM_DATE TO_DATE MY_TM_FORMAT
---------------------- ---------------------- -------------------
11/12/2015 07:39:14 AM 11/12/2015 03:39:14 PM 07:39 AM - 03:39 PM
NOTE:
The WITH clause is only to create the sample data for demonstration. Use the following query with your table, which is the same as you are using currently. The point is that you need to validate your data as TO_CHAR doesn't manipulate the data.
SELECT from_date,
to_date,
TO_CHAR(from_date, 'HH:MI PM')
||' - '
||TO_CHAR(to_date, 'HH:MI PM') my_tm_format
FROM your_table;
TO_CHAR is capable to convert the time element in 12-hour format irrespective of the format model you specify for the time element.

According to desired output (no leading zero on hour) it should be this one:
SELECT
TO_CHAR(time_from, 'fmHH:')||TO_CHAR(time_from, 'MI PM') || ' - ' ||
TO_CHAR(to_from, 'fmHH:')||TO_CHAR(to_from, 'MI PM')
FROM table_name;
or
SELECT
REGEXP_REPLACE(TO_CHAR(time_from, 'HH:MI PM'), '^0') || ' - ' ||
REGEXP_REPLACE(TO_CHAR(to_from,'HH:MI PM'), '^0')
FROM table_name;

Related

Use NVL with date conversion function returns ORA-01843: not a valid month error

I have the below SQL (Oracle) that is erroring with ORA-01843: not a valid month error when I do not pass dates into the :P_FROM_DATE and :P_TO_DATE parameters. For some reason it is not accepting the alternate date values (sysdate-30, sysdate-1).
It does work properly if I pass dates into the two parameters. How can I modify this to work?
AND pha.CREATION_DATE BETWEEN
NVL(to_date(to_char((:P_FROM_DATE),'YYYY-MM-DD')||' 00:00:00','YYYY-MM-DD HH24:Mi:SS') , sysdate-30)
AND
NVL( to_date(to_char((:P_TO_DATE),'YYYY-MM-DD')||' 23:59:59','YYYY-MM-DD HH24:Mi:SS') , sysdate-1)
That's because you applied NVL function on the wrong place. You should apply it to parameters themselves, not the whole expression:
AND pha.CREATION_DATE BETWEEN
to_date(nvl(:P_FROM_DATE, to_char(sysdate - 30, 'yyyy-mm-dd')) ||' 00:00:00', 'YYYY-MM-DD HH24:Mi:SS')
AND
to_date(nvl(:P_TO_DATE , to_char(sysdate - 1 , 'yyyy-mm-dd')) ||' 23:59:59', 'YYYY-MM-DD HH24:Mi:SS');
For example (in which I use SQL*Plus and substitution variables; you'd still use bind ones in your code):
SQL> with pha (name, creation_date) as
2 (select 'Little', date '2022-11-01' from dual union all
3 select 'Foot' , date '2019-08-25' from dual
4 )
5 select *
6 from pha
7 where 1 = 1
8 AND pha.CREATION_DATE BETWEEN
9 to_date(nvl('&P_FROM_DATE', to_char(sysdate - 30, 'yyyy-mm-dd')) ||' 00:00:00', 'YYYY-MM-DD HH24:Mi:SS')
10 AND
11 to_date(nvl('&P_TO_DATE' , to_char(sysdate - 1 , 'yyyy-mm-dd')) ||' 23:59:59', 'YYYY-MM-DD HH24:Mi:SS');
Enter value for p_from_date: --> NULL values passed to
Enter value for p_to_date: --> both parameters
NAME CREATION_D
------ ----------
Little 2022-11-01
SQL>
Or, with values passed to the query:
SQL> /
Enter value for p_from_date: 2019-07-13
Enter value for p_to_date: 2019-09-30
NAME CREATION_D
------ ----------
Foot 2019-08-25
SQL>

How to insert data into oracle database table using PL SQL which includes 365 days of the year

I already have a table built in oracle. I'm trying to insert some data that looks like this:
But, I can't seem to be able to add the DATE together with the ID, YEAR and INDICATOR.
I manage to get the DATE from 1/1/2019 7:00:00 PM - 12/31/2019 7:00:00 PM.
CODE:
INSERT INTO TABLE(DATE)
select to_date('01-01-2019 7:00:00 PM', 'DD-MM-YYYY HH:MI:SS PM') + rownum -1 dt from dual
connect by level <= to_date('05-01-2019 7:00:00 PM', 'DD-MM-YYYY HH:MI:SS PM') -
to_date('01-01-2019 7:00:00 PM', 'DD-MM-YYYY HH:MI:SS PM') + 1;
When I exclude DATE, it looks like this:
CODE:
INSERT INTO TABLE (ID, YEAR, INDICATOR)
Values (sequ.nextval, '2019', 'X') ;
I tried to combine the two codes but it doesn't work. Is there any other ways I can do to make it works? Or I'm doing it the wrong way?
The only change data is the DATE because I need it to be 365 days of 2019.
YEAR and INDICATOR remain the same for all data.
Is this what you want?
insert into table(id, "date", "year", indicator)
select rownum, dt, extract(year from dt), 'X'
from (select to_date('01-01-2019 7:00:00 PM', 'DD-MM-YYYY HH:MI:SS PM') + rownum - 1 as dt
from dual
connect by level <= to_date('05-01-2019 7:00:00 PM', 'DD-MM-YYYY HH:MI:SS PM') -
to_date('01-01-2019 7:00:00 PM', 'DD-MM-YYYY HH:MI:SS PM') + 1
) t;
Even shorter (assuming you can calculate your current year):
insert into table( id, date, year, indicator)
select sequ.nextval, to_date('31-12-2018 07:00:00', 'DD-MM-YYYY HH24:MI:SS') + rownum, 2019, 'X' from all_objects where rownum <= 365
Or, if you prefer not to use the ALL_OBJECTS table:
insert into table( id, date, year, indicator)
select sequ.nextval, to_date('31-12-2018 07:00:00', 'DD-MM-YYYY HH24:MI:SS') + level, 2019, 'X' from dual connect by level <= 365

Inject character to date column

I have a date column.
select RETAIL_ACQUISITION_DTTM from XXXXX.TABLE_2348
13/07/2018
I want to select the value as such it returns as below,
2018-07-13T00:00:00
so it has to display the date as YYYY-MM-DD with T and then HH24:MI:SS
You need to convert your string (why is it stored as a string?) to a date using a format model that matches the actual string value:
to_date(RETAIL_ACQUISITION_DTTM, 'DD/MM/YYYY')
Having that format model wrong is why you get the 0013 year in your result.
Then you can convert that date back to a string with to_char(), and you can embed the fixed T as a character literal with double quotes, using a format model like 'YYYY-MM-DD"T"HH24:MI:SS':
with TABLE_2348 (RETAIL_ACQUISITION_DTTM) as (
select '13/07/2018' from dual
)
select to_char(to_date(RETAIL_ACQUISITION_DTTM, 'DD/MM/YYYY'),
'YYYY-MM-DD"T"HH24:MI:SS') as RETAIL_ACQUISITION_DTTM
from XXXXX.TABLE_2348;
RETAIL_ACQUISITION_
-------------------
2018-07-13T00:00:00
You could also just ignore that it is a date and use string manipulation:
with TABLE_2348 (RETAIL_ACQUISITION_DTTM) as (
select '13/07/2018' from dual
)
select substr(RETAIL_ACQUISITION_DTTM, 7, 4)
|| '-' || substr(RETAIL_ACQUISITION_DTTM, 4, 2)
|| '-' ||substr(RETAIL_ACQUISITION_DTTM, 1, 2)
|| 'T00:00:00' as RETAIL_ACQUISITION_DTTM
from XXXXX.TABLE_2348;
RETAIL_ACQUISITION_
-------------------
2018-07-13T00:00:00
If the column is actually a date rather than a string then you are doing unnecessary conversions, including implicit ones which rely on your NLS settings, and you are losing the original time from the value if it was not midnight anyway:
alter session set nls_date_format = 'DD-MON-RR';
with TABLE_2348 (RETAIL_ACQUISITION_DTTM) as (
select to_date('2018-07-13 12:34:56', 'YYYY-MM-DD HH24:MI:SS') from dual
)
select to_char(to_date(RETAIL_ACQUISITION_DTTM, 'YYYY-MM-DD-HH24:MI:SS'),
'YYYY-MM-DD HH24:MI:SS') as RETAIL_ACQUISITION_DTTM from XXXXX.TABLE_2348;
RETAIL_ACQUISITION_
-------------------
0013-07-20 18:00:00
That is really doing:
to_char(
to_date(
to_char(
RETAIL_ACQUISITION_DTTM,
'DD-MON-RR'), ---- from your session NLS_DATE_FORMAT setting
'YYYY-MM-DD-HH24:MI:SS'),
'YYYY-MM-DD HH24:MI:SS')
If you skip to extra steps you can just format the date directly:
with TABLE_2348 (RETAIL_ACQUISITION_DTTM) as (
select to_date('2018-07-13 12:34:56', 'YYYY-MM-DD HH24:MI:SS') from dual
)
select to_char(RETAIL_ACQUISITION_DTTM,
'YYYY-MM-DD"T"HH24:MI:SS') as RETAIL_ACQUISITION_DTTM
from XXXXX.TABLE_2348;
RETAIL_ACQUISITION_
-------------------
2018-07-13T12:34:56
which also doesn't rely on your NLS settings, so won't break in interesting ways if it's run in another session with different settings.
replace sysdate with your column name if its date type.
Using Single to_char:
select to_char(sysdate,'--YYYY-MM-DD"T"hh24:mi:ss') from dual;
Using two to_char and concatenation for simplification.
select to_char(sysdate,'--'||'YYYY-MM-DD')||'T'||to_char(sysdate,'hh24:mi:ss') from dual; -- 13/07/2018
select '--'||to_char(sysdate,'YYYY-MM-DD')||'T'||to_char(sysdate,'hh24:mi:ss') from dual; -- 13/07/2018

12 Hours format in oracle

I have function that receive user name and return time in , time out and username in one column.
I used substring to make it into 3 columns and time out return as 24 hours format and I need it into 12 hours format.
select substr( FUN1('username'),1,5) TIMEIN ,
substr( FUN1('username'),7,6) TIMEOUT,
substr( FUN1('username'),12,100) NAME from dual;
Use the TO_CHAR function
SELECT TO_CHAR(substr( FUN1('username'),1,5), 'DD-MM-YYYY HH:MI:SS AM') TIMEIN,
TO_CHAR(substr( FUN1('username'),7,6), 'DD-MM-YYYY HH:MI:SS AM') TIMEOUT,
substr( FUN1('username'),12,100) NAME
FROM dual;
You can do this by converting the TIMEOUT to a date using TO_DATE assuming the time is in 24 hours format, and then re-converting it to a string using TO_CHAR with the format as 12 hours format -
select to_char(to_date('13:00', 'HH24:MI'),'HH:MI AM') from dual;
Here's how your SQL in the question would look like for the TIMEOUT -
select substr( FUN1('username'),1,5) TIMEIN ,
to_char(to_date(substr( FUN1('username'),7,6), 'HH24:MI'),'HH:MI AM') TIMEOUT,
substr( FUN1('username'),12,100) NAME from dual;

I want to trim the Time into specific format in oracle sql for Difference Coulm [duplicate]

This question already has answers here:
format interval with to_char
(7 answers)
Closed 8 years ago.
When i am taking the difference between the two timing i need to display whether it is positive or negative.
select a.jobname,
round((to_date(to_char(a.Lastupdatedatetime, 'DD/MM/YYYY HH:MI:SS AM'),
'DD/MM/YYYY HH:MI:SS AM') -
to_date(to_char(a.Creationdatetime, 'DD/MM/YYYY HH:MI:SS AM'),
'DD/MM/YYYY HH:MI:SS AM'))*24*60,2) as duration_Staging,
round((to_date(to_char(b.Lastupdatedatetime, 'DD/MM/YYYY HH:MI:SS AM'),
'DD/MM/YYYY HH:MI:SS AM') -
to_date(to_char(b.Creationdatetime,'DD/MM/YYYY HH:MI:SS AM'),
'DD/MM/YYYY HH:MI:SS AM'))*24*60,2) as duration_Prod,
substr(((a.lastupdatedatetime - a.creationdatetime) -
(b.lastupdatedatetime - b.creationdatetime)), 11, 10) as Difference
from production.scheduledjob a,
production.scheduledjob b
where a.jobstatuscv='C'
and b.jobstatuscv='C'
and a.effectivedate=to_char(sysdate-3,'DD-MON-YYYY')
and b.effectivedate=to_char(sysdate-4,'DD-MON-YYYY')
and a.jobname=b.jobname order by Difference desc;
Above query output is:
JOBNAME DURATION_STAGING DURATION_PROD DIFFERENCE
PershingStarToPace 90.43 145.4 -000000000 00:54:57.79
PershingUpdateMarketValue 15.05 54.53 -000000000 00:39:28.87
I Need output as below :
JOBNAME DURATION_STAGING DURATION_PROD DIFFERENCE
PershingStarToPace 90.43 145.4 -00:54:57.79
PershingUpdateMarketValue 15.05 54.53 -00:39:28.87
Table description
Name Null? Type
----------------------------------------- -------- ----------------------------
SCHEDULEDJOBID NOT NULL NUMBER(22)
EFFECTIVEDATE NOT NULL DATE
JOBSTATUSCV VARCHAR2(10)
CREATIONDATETIME NOT NULL TIMESTAMP(6)
CREATEDBY NUMBER(22)
LASTUPDATEDATETIME NOT NULL TIMESTAMP(6)
LASTUPDATEDBY NUMBER(22)
JOBID NUMBER(22)
SCHEMANAME NOT NULL VARCHAR2(100)
MESSAGE VARCHAR2(1000)
JOBNAME VARCHAR2(100)
SERVERNAME VARCHAR2(100)
JOBGROUP VARCHAR2(100)
WORKGROUPID NUMBER(22)
JOBGROUPID NUMBER(22)
It looks like TO_CHAR() is not really usable for INTERVAL data types. So you have to do it manually, for example like this:
SELECT
REGEXP_SUBSTR(((a.lastupdatedatetime - a.creationdatetime) - (b.lastupdatedatetime - b.creationdatetime)), '^-?')
|| REGEXP_SUBSTR(((a.lastupdatedatetime - a.creationdatetime) - (b.lastupdatedatetime - b.creationdatetime)), '\d{2}:\d{2}:\d{2}\.\d{2}')
FROM ...
EXTRACT does not work, because the leading "-" is added before each component, i.e.
SELECT
EXTRACT(HOUR FROM ((a.lastupdatedatetime - a.creationdatetime) - (b.lastupdatedatetime - b.creationdatetime)) || ':' ||
EXTRACT(MINUTE FROM ((a.lastupdatedatetime - a.creationdatetime) - (b.lastupdatedatetime - b.creationdatetime)) || ':' ||
EXTRACT(SECOND FROM ((a.lastupdatedatetime - a.creationdatetime) - (b.lastupdatedatetime - b.creationdatetime))
FROM ...
returns 0:-54:-57.79 for instance.