Oracle SQL - convert a varchar2 into a date - sql

I have a problem with converting a varchar2 fields into a date format.
I got 2 columns with the datatyp varchar2, one is called qtime the other is called ztime. Both fields contain strings in this format (f.e. 152015 -> would be a timestamp 15:20:15).
For reporting reasons I need to convert this fields into a date format, afterwards I want to substract (qtime-ztime) the fields an convert them into the format [hh] (f.e. after the operation 01:20:00 would be -> 01). Is it possible to to this within Oracle SQL 12c? The biggest problem for me right now is that I don't get those Strings converted into a date format.
select TO_DATE(qtime,'MM/DD/YYYY hh24:mi:ss') just gives me
ORA-01861:"literal does not match format string"
select TO_DATE(qtime,'hh24mmss') gives me a wrong Date
01.03.2018
select TO_TIMESTAMP(qtime,'hh24mmss') gives me a wrong Date
01.03.2018 BUT the correct time with f.e. 15:20:15,0000000
Thank you in advance, any help is appreciated
Note: I only have reading rights on the database Oracle 12c, so I need to to this within Statements

"The Database contains another column with the correct date for each time"
The missing piece of the puzzle! Concatenate the two columns to get something which can be converted to an Oracle DATE:
select to_date(qdate||qtime, 'yyyymmddhh24miss') as qdatetime
, to_date(zdate||ztime, 'yyyymmddhh24miss') as zdatetime
from your_table
Once you have done that you can perform arithmetic of the dates e.g.
select id
, zdatetime - qdatetime as time_diff
from ( select id
, to_date(qdate||qtime, 'yyyymmddhh24miss') as qdatetime
, to_date(zdate||ztime, 'yyyymmddhh24miss') as zdatetime
from your_table
)
If you want the number of hours in the difference you can include this expression in the projection of the outer query:
, extract( hour from (zdatetime - qdatetime) day to second) as hrs_ela

First off, if you are trying to convert a varchar2 into a date without specifying neither day nor month, it will default to the first day of the current month:
If you specify a date value without a date, then the default date is the first day of the current month.
You can read up more here
Also in 2nd and 3rd your example, you are using 'hh24mmss' for specifying hour, minute and second components, but do note that correct format for minutes is 'mi' and not 'mm', which is used for months.
So the solution is to concatenate both date and time component when creating the date as the other answer suggested, tho I would recommend using a single date field as it can store the information you need.

Related

SQL Oracle table blank when trying to query date data stored as varchar

I have a column called received_dt_key in Varchar in the format DD-MM-YYYY (e.g. 30-07-2021).
I would like to select all from the table for dates between 31-12-2021 and 01-01-2022. I have tried version of the below query and a blank table is the output.
SELECT *
FROM SD_BDAY
WHERE to_char(to_date(RECEIVED_DT_KEY, 'DD-MM-YYYY')) > to_char(to_date('31-12-2021', 'DD-MM-YYYY'))
and to_char(to_date(RECEIVED_DT_KEY, 'DD-MM-YYYY')) < to_char(to_date('01-01-2022', 'DD-MM-YYYY'));
Don't compare dates as strings. Compare them as dates:
SELECT *
FROM SD_BDAY
WHERE to_date(RECEIVED_DT_KEY, 'DD-MM-YYYY') > to_date('31-12-2021', 'DD-MM-YYYY')
and to_date(RECEIVED_DT_KEY, 'DD-MM-YYYY') < to_date('01-01-2022', 'DD-MM-YYYY');
If you try to compare them as strings then you are looking for string that is greater than '31-12-2021' and less than '01-01-2022' and the string comparison will look at the first character and see if it can find a match which is greater than '3' and less than '0'; there can never be such a match so it is quite correct that when comparing as strings nothing is returned.
As pointed out by #AlexPoole in comments, even if you compare the values as dates (rather than strings) you will still never return a result as finding values that are greater than DATE '2021-12-31' and less than DATE '2022-01-01' would return all dates from 2021-12-31 00:00:01 to 2021-12-31 23:59:59; however, your values will always be converted with a midnight time component and, therefore, will never fall into that range so cannot be returned.
What you probably want is to use >= rather than > and then it would match values on 2021-12-31.
The best thing would be to store calendar dates in date data type column. Why else do you think Oracle designed that data type? This way you may create normal indexes on data data type columns, or, if needed, partition the table by that date column.
Still, if you insist in having the calendar dates stored like that, I think the below should work:
SELECT *
FROM SD_BDAY
WHERE to_date(RECEIVED_DT_KEY, 'DD-MM-YYYY') >
to_date('31-12-2021', 'DD-MM-YYYY')
and to_date(RECEIVED_DT_KEY, 'DD-MM-YYYY') <
to_date('01-01-2022', 'DD-MM-YYYY');
Thus you compare calandar dates with calendar dates, not varchar with varchar, as it results from the code you have written.
And what if in the varchar2 column there is somethibng that can't be converted to date? That is why it is best to use the date data type.

count records in specific date format with SQL

i'm trying to define a rule that count rows where date format is dd/mm/yyyy and greater than a specific date in sql but i couldn't find the right function to use.
The second part is working : SELECT COUNT (*) FROM CUSTOMER WHERE DAT_0 >= '01/01/1995' but how could i specify the format too
In Standard SQL, the WHERE clause would look like:
WHERE DAT_0 >= DATE '1995-01-01'
Many databases would simply accept this without the DATE as well:
WHERE DAT_0 >= '1995-01-01'
In your comment DATE_0 is a date column
Therefore we can change it to any format as below using to_char then to_date
to_date(to_char(DATE_0,'yyyymmdd'),'yyyy-mm-dd')
When comparing you can try this, converting the date to_number, i find it very easy
to_number(to_char(DATE_0,'yyyymmdd')) > 19950101
if datatype of "DAT_0" is date or datetime or timestamp , they are recorded as a specific format specified by default datetime setting in your database engine , therefore you can't have multiple format inside the column , so there is no concern there

Convert date to month year format and pass it in the query

I have a BIRT report where user will be entering the dates in dd-mm-yyyy format however I need to convert dd-mm-yyyy to MON-YYYY format.
I have tried to use VARCHAR_FORMAT(FIELDNAME,'MON-YYYY') however it doesn't work.
select …….
where VARCHAR_FORMAT(fieldname,'MON-YYYY') = '2017-05-15';
User would end the date as
15/05/2017
The value present in the database for this field is 2017-05-15 07:30:00.0
update
Apparently the column is not a string but a datetime which means the conversion is only
to_date(fieldname, 'MON-YYYY')
But if the column is used in a Where clause it shouldn’t be converted at all.
——
Use to_date and to_char to first convert your string to a date and then back to a string with the right format
to_char(to_date(fieldname, 'DD-MM-YYYY'), 'MON-YYYY')
select *
from table (values
timestamp('2017-05-15-07.30.00')
) t(fieldname)
where
fieldname between to_date('15/05/2017', 'DD/MM/YYYY') and to_date('15/05/2017', 'DD/MM/YYYY') + 1 day
--date(fieldname) = to_date('15/05/2017', 'DD/MM/YYYY')
;
You may run it as is.
Both cases work, but to use the 2-nd one efficiently, you must create an index by the date(fieldname) expression (since db2 10.5) or add generated always column to the table with the same expression and index on it.

Query to Change Quarter Timestamp Format

I have a varchar2(2000) byte column which stores the data as- 'Q2 FY07' OR 'Q3 FY08' i need data in this format now- '2007Q2' OR '2008Q3' . Can anyone help me what should i query the sata as in oracle.
First of all (and as usual), you should not store DATE values as VARCHAR, even if you need only the quarter.
You can do following. First convert the string into a DATE, e.g.
SELECT
TO_DATE(REGEXP_SUBSTR('Q2 FY07', '\d{2}$')||'-'||REGEXP_SUBSTR('Q2 FY07','\d')*3, 'RR-MM')
FROM ...
Then you can change the output format according to your needs, i.e.
TO_CHAR(
TO_DATE(REGEXP_SUBSTR('Q2 FY07', '\d{2}$')||'-'||REGEXP_SUBSTR('Q2 FY07','\d')*3, 'RR-MM')
, 'YYYY"Q"Q')

To get all the dates in a format dd/mm/yyyy. I have a date field in the format yyyymmdd

In my DB, there is a date field in the format yyyymmdd.
I have to get all the dates in the format dd-mm-yyyy for that particlar date.
ex:
Date
20170130
20170228
20170325
for the above dates, I need the output in the below format with the dates and day of the particular dates
date day
30-01-2017 tuesday
28-02-2017 tuesday
25-03-2017 saturday
If the column is a string, then it can hold invalid date values such as February 31, one way to avoid this is by a small function such as this:
create or replace
function my_to_date( p_str in varchar2 ) return date
is
begin
return to_date( p_str );
exception
when others then
return null;
end;
\\
select to_char(my_to_date('20170231'),'DD-MM-YYYY Day')
from dual
\\
Demo
Try below:
Select to_char(yrdate, 'dd-mm-yyyy'), to_char(yrdate, 'D') from yrtable
It sounds like your dates aren't actually DATE fields but some kind of CHAR field? The best option would be to convert to DATE and then convert back to CHAR:
SELECT TO_CHAR(TO_DATE(mydate, 'YYYYMMDD'), 'DD-MM-YYYY Day')
FROM mytable;
This uses the YYYYMMDD mask to convert your string into a date, then uses the mask DD-MM-YYYY Day to convert it back into a string. Use day if you want the day name in lowercase (as in your OP).
#user2778168 answer will give you the results you want. But why?
Your database does not have dates stored in yyyymmdd format or any other date format for at mater, unless it's defined with a character type definition. Oracle stores all dates in a single internal structure, and with only slight variations timestamps are the same. The format used only tells Oracle how to display the value or to convert a string to a date. Unless a specific format is specified Oracle uses the NLS_DATE_FORMAT for this determination. See here and scan down to "Datetime Format Models" for format specifications.
To see this run the following:
select value
from nls_session_parameters
where parameter = 'NLS_DATE_FORMAT';
Select yrdate default_format
, to_char(yrdate, 'dd-mm-yyyy') specified_format
, dump(yrdate) unformated
from yrtable;
alter session set nls_date_format = 'Month dd,yyyy';
Rerun the above queries.
It seems you hold date column(date1) in character format. Suppose you have a table named days:
SQL> desc days
date1 varchar2(10)
then,
we should convert it into date, and then into char format, with aliases in quotation marks to provide lowercase aliases as you wanted.
perhaps your database's date language is non-english like mine(turkish), then you need to convert it to english.
lastly, it'a appropriate to order the results according to converted date, seen from your output. So we can use the following SQL :
select to_char(to_date(date1,'yyyymmdd'),'dd-mm-yyyy') "date",
to_char(to_date(date1,'yyyymmdd'),'day','nls_date_language=english') "day"
from days
order by to_date(date1,'yyyymmdd');
D e m o