I need to convert Decimal to date. I have a decimal date field that contains data like this :
1,132,009.00 --1/13/2009
7,152,004.00 --7/15/2004
11,012,005.00 --11/01/2005
etc
I would like it to read as xx/xx/xxxx.
Is there anyway to do this with SQL commands or DB2 logic in a select statement?
SELECT column1 from table1 ;
WITH x(decvalue) AS ( VALUES (DECIMAL(1132009.00)),(DECIMAL(7152004.00)),(DECIMAL(11012005.00)) )
SELECT CAST(
LPAD( RTRIM( CHAR( INTEGER( decvalue/1000000 ))), 2, '0' ) || '/' ||
LPAD( RTRIM( CHAR( MOD( decvalue/10000, 100 ))), 2, '0' ) || '/' ||
MOD( decvalue, 10000 )
AS CHAR(10))
AS chardateresult
FROM x
;
Using the same WITH values as #Fred, I came up with:
WITH x(decvalue) AS ( VALUES (DECIMAL(1132009.00)),(DECIMAL(7152004.00)),(DECIMAL(11012005.00)) )
SELECT TO_DATE(CHAR(CAST(decvalue AS DECIMAL(8,0))), 'MMDDYYYY')
FROM x
This assumes that your input values aren't going to be longer than 8 digits (2 for month, 2 for day, 4 for year), otherwise you'll get an overflow error on the cast. It will also fail if there's not at least some value for each of month, day, and year (00002011 would not work, for example, but 01012011 would).
Related
I working for a client who uses PROGRESS database SQL (i didn't knew this kind of database, so it's my first time that i work on it).
My problem it's all the dates are in Julian-date, and i want to convert them into datetime. But i haven't found any document or help online that deals with this.
The only document i found it's:
https://knowledgebase.progress.com/articles/Article/How-to-Obtain-a-Julian-Date-in-Progress
But i want to do exactly the opposite.
For example in postgresql:
select to_timestamp(column1::text,'J')
from table1
But on PROGRESS it's harder and there is less information and examples than the others databases on the web
Thank you in advance for your help
Character
In case your Julian date is stored in a field with the character data type, you can use instr to pull it apart and then reassemble it into a timestamp:
select
-- my character field containing 92182.3966
descr,
-- get the year
floor( cast( left( descr, instr( descr, '.' ) - 1 ) as integer ) / 1000 ) as 'year',
-- get the day
mod( cast( left( descr, instr( descr, '.' ) - 1 ) as integer ), 1000 ) as 'day',
-- get the time
cast(
'0' + right( descr, length( descr ) - instr( descr, '.' ) + 1 )
as float
) as 'time',
-- combine all to timestamp
cast(
-- get first day of year
cast(
to_char(
floor( cast( left( descr, instr( descr, '.' ) - 1 ) as integer ) / 1000 )
+ 1900 -- !!! beware
)
+ '-01-01'
as date
)
-- add days
+ mod( cast( left( descr, instr( descr, '.' ) - 1 ) as integer ), 1000 )
as timestamp
)
-- add milliseconds
+ cast(
cast(
'0' + right( descr, length( descr ) - instr( descr, '.' ) + 1 )
as float
) * 86400 * 1000
as integer
) as 'timestamp'
from pub.ddcapp
where application = 'JULIAN'
This reports that the time is 1992-07-01 09:31:06.24 which is 1 second later than what your link states it was translated from.
Decimal
If on the other hand your field is a decimal, it is a lot simpler:
select
-- my decimal field containing 92182.3966
open_bal,
-- get the year
floor( open_bal / 1000 ) as 'year',
-- get the day
mod( open_bal, 1000 ) as 'day',
-- get the time
open_bal - floor( open_bal ) as 'time',
-- combine all to timestamp
cast(
cast(
to_char(
floor( open_bal / 1000 )
+ 1900 -- !!!
)
+ '-01-01'
as date
)
+ mod( open_bal, 1000 )
as timestamp
)
+ ( open_bal - floor( open_bal ) ) * 86400 * 1000
as 'timestamp'
from pub.ledbal
where adm_nr = 0
There is a requirement where I need to validate the identity card number with the first 6 digits as DOB. I need to find out the users not maintaining correct format.
If the dob is 02/10/1983 - 83021023456 && if its 02/10/2083 ->83221023456 (DOB is in MM/DD/YYYY and if year of birth >2000 then the +20 is done to the dob month). The query I tried with is given below:-
SELECT f_account_name,F_SSN ,F_DOB from table where
CASE WHEN SUBSTR(to_char(F_DOB, 'YYYY-MM-DD'),0,4)>2000
THEN
SUBSTR(f_ssn,0,6) <>
SUBSTR(to_char(F_DOB, 'YY-MM-DD'),0,2)
||SUBSTR(to_char(F_DOB, 'YY-MM-DD'),4,2)
||SUBSTR(to_char(F_DOB, 'YY-MM-DD'),7,2)
ELSE
SUBSTR(f_ssn,0,6) <>
SUBSTR(to_char(F_DOB, 'YY-MM-DD'),0,2)
||(SUBSTR(to_char(F_DOB, 'YY-MM-DD'),4,2)+20)
||SUBSTR(to_char(F_DOB, 'YY-MM-DD'),7,2)
END;
Its not working .
You cannot have the comparison inside the CASE expression; since the left-hand side of the expression is identical then it is simple to move it out and then you can simplify the rest:
SELECT f_account_name,
F_SSN,
F_DOB
FROM table_name
WHERE SUBSTR(f_ssn,0,6) !=
CASE
WHEN EXTRACT( YEAR FROM F_DOB ) > 2000
THEN TO_CHAR( F_DOB, 'YYMMDD')
ELSE TO_CHAR( F_DOB, 'YY' )
|| TO_CHAR( EXTRACT( MONTH FROM F_DOB )+20, 'FM00' )
|| TO_CHAR( F_DOB, 'DD')
END;
or, if the rule is to add 20 to the month for each century past 1900 (i.e. 20XX add 20 and 21XX add 40, etc.) then:
SELECT f_account_name,
F_SSN,
F_DOB
FROM table_name
WHERE SUBSTR(f_ssn,0,6) !=
TO_CHAR( F_DOB, 'YY' )
|| TO_CHAR(
EXTRACT( MONTH FROM F_DOB )
+ 20 * GREATEST( TRUNC( EXTRACT( YEAR FROM F_DOB ) / 100 ) - 19, 0 ),
'FM00'
)
|| TO_CHAR( F_DOB, 'DD');
I tried some date arithmetics and worked with numbers rather than strings ...
WITH
-- your input
indata(f_account_name,f_ssn,f_dob) AS (
--string -- number -- string
SELECT 'Arthur',83021023456,'02/10/1983' FROM dual
UNION ALL SELECT 'Tricia',83221023456,'02/10/2083' FROM dual
)
SELECT
f_account_name
, f_ssn
, f_dob
FROM indata
WHERE CAST(TRUNC(f_ssn/100000) AS NUMBER(6))
-- ^ integer division by 100000 to get the first 6 digits ...
= MOD(EXTRACT(YEAR FROM TO_DATE(f_dob,'MM/DD/YYYY')),100) * 10000
-- ^ modulo year of date of 100 gives 3rd and 4th digit of year
+ (
EXTRACT(MONTH FROM TO_DATE(f_dob,'MM/DD/YYYY'))
+CASE
WHEN EXTRACT(YEAR FROM TO_DATE(f_dob,'MM/DD/YYYY')) >= 2000 THEN 20
ELSE 0
END
) * 100
+ EXTRACT(DAY FROM TO_DATE(f_dob,'MM/DD/YYYY'))
;
I have a column called duration_d which is varchar2 and the data in that table looks like below
duration_d
-----------
12:25
01:35
12:10
04:21
12:18
12:24
I tried below query
SELECT SUM( to_date( duration_d, 'mi:ss' ))
FROM table
GROUP BY calling_number;
When I execute it following error is coming
ORA-00933: SQL command not properly ended
00933. 00000 - "SQL command not properly ended"
can any one tell me how to make sum it?
To get the total as fractions of a day you can use:
SELECT SUM( TO_DATE( duration_d, 'MI:SS' ) - TO_DATE( '00:00', 'MI:SS' ) ) AS total
FROM your_table
Which gives the result:
TOTAL
------------------------------------------
0.0383449074074074074074074074074074074074
To convert this to an interval data type you can use NUMTODSINTERVAL:
SELECT NUMTODSINTERVAL(
SUM( TO_DATE( duration_d, 'MI:SS' ) - TO_DATE( '00:00', 'MI:SS' ) ),
'DAY'
) AS total
FROM your_table
Which gives the result:
TOTAL
-------------------
+00 00:55:13.000000
Please try below:
with x as
(select sum((regexp_substr(YOUR_COLUMN, '[0-9]+', 1, 1)*60) +
regexp_substr(id, '[0-9]+', 1, 2)) seconds
from YOUR_TABLE)
SELECT
TO_CHAR(TRUNC(seconds/3600),'FM9900') || ':' ||
TO_CHAR(TRUNC(MOD(seconds,3600)/60),'FM00') || ':' ||
TO_CHAR(MOD(seconds,60),'FM00')
FROM x
Will work only if the duration is always [MI:SS].
Also you can add the group by as per your requirement.
Converting Seconds to the required duration format Reference.
Group By
with x as
(select calling_number,sum((regexp_substr(YOUR_COLUMN, '[0-9]+', 1, 1)*60) +
regexp_substr(id, '[0-9]+', 1, 2)) seconds
from YOUR_TABLE
group by calling_number)
SELECT calling_number,
TO_CHAR(TRUNC(seconds/3600),'FM9900') || ':' ||
TO_CHAR(TRUNC(MOD(seconds,3600)/60),'FM00') || ':' ||
TO_CHAR(MOD(seconds,60),'FM00')
FROM x
Use a combination of SUBSTR, to_char, to_date, NVL, INSTR, reverse and SUM.
SELECT "calling_number",
to_char(to_date(SUM(NVL(SUBSTR("duration_d", 0, INSTR("duration_d", ':')-1), "duration_d"))*60 +
SUM(substr("duration_d", - instr(reverse("duration_d"), ':') + 1)),'sssss'),'hh24:mi:ss') AS SUM_DURATION_D
FROM yourtable
GROUP BY "calling_number"
Output
calling_number SUM_DURATION_D
1 00:26:10
2 00:29:03
SQL Fiddle: http://sqlfiddle.com/#!4/9b0a81/33/0
Correct spelling as below
SELECT SUM( TO_DATE( duration_d, 'mi:ss' ) )
FROM YOURTABLE Group By calling_number
I'm looking to convert an integer to Days using a db2 database. The integers are in this format 20130101 or YYYYMMDD. I believe you have to write a custom function after converting the integer to a char but I was unsure of how to do the second conversion to DAYS. I'm looking for a returned format January, 1, 2013 from 20130101.
WITH
/*****************************************************
*** Sample Data ***
*****************************************************/
sample_data
( START_DATE , END_DATE ) AS
(
VALUES
(20130101, 20131227 )
, (20130930, 20131230 )
, (20130411, 20130912 )
, (20130410, 20140101 )
)
,
t2(START_DATE, END_DATE) AS
( SELECT
CAST(SUBSTR(START_DATE, 1,4) CONCAT '-'
CONCAT SUBSTR(START_DATE, 5,2) CONCAT '-'
CONCAT SUBSTR(START_DATE, 7,2) AS CHAR(15)),
CAST(SUBSTR(END_DATE, 1,4) CONCAT '-'
CONCAT SUBSTR(END_DATE, 5,2) CONCAT '-'
CONCAT SUBSTR(END_DATE, 7,2) AS CHAR(15))
FROM SAMPLE_DATA
)
SELECT
START_DATE,
END_DATE
FROM t2
You can use this:
select monthname(to_date(20130101, 'YYYYMMDD')) || ', ' ||
day(to_date(20130101, 'YYYYMMDD')) || ', ' ||
year(to_date(20130101, 'YYYYMMDD')) from sysibm.sysdummy1
The result is:
January, 1, 2013
Replace the integer 20130101 by your field name.
If you will be using the conversion in several places, it's probably better to create a function to avoid repeating the field and conversions.
You could also cut a few corners using aritmetics to get year and day, such as this:
select monthname(to_date(20130101, 'YYYYMMDD')) || ', ' ||
mod(20130101, 100) || ', ' || to_char(20130101 / 10000) from sysibm.sysdummy1
The result is the same.
It's a lot of casting, but you can use the TIMESTAMP_FORMAT function:
date(timestamp_format(char(start_date),'YYYYMMDD'))
Keep in mind that this just gets you a value that is an actual DATE, not necessarily in the "pretty" format that you list above.
I'd like to format a number as "1st", "2nd", "4th", "9th", etc. Is there an Oracle function that will do this for me?
Assuming the value supplied is numeric, rather than DATE, you can use TO_CHAR but you have to convert the numeric value to a string, then a DATE (Julian) before ultimately formatting it:
SELECT TO_CHAR(TO_DATE('1', 'dd'), 'ddth')
FROM DUAL
Result:
01st
When testing, using 'd' for the format didn't return expected results because the value is interpreted as a Julian date. Either substring the output to remove the leading zero, or provide a full date string (doesn't matter to the TO_CHAR because it's only interested in the day of the month):
SELECT TO_CHAR(TO_DATE('1900-01-01', 'YYYY-MM-dd'), 'dth')
FROM DUAL
Because calendar days end at 31, use the year value instead to handle numbers greater than 31:
SELECT TO_CHAR(TO_DATE('32-01-01', 'YYYY-MM-dd'), 'yyth')
FROM DUAL
Result:
32nd
Maybe I'm oversimplifying, but it seems like the following should work just fine (for integers) and is a lot more readable than converting to a date and back:
select case
when initial_extent is null then null
when substr(initial_extent,-2,1) = '1'
then initial_extent || 'th'
else case substr(initial_extent,-1,1)
when '1' then initial_extent || 'st'
when '2' then initial_extent || 'nd'
when '3' then initial_extent || 'rd'
else initial_extent || 'th'
end
end as formatted_number
from user_tables
select substr( to_char( to_date( abs( decode( mod( l_value, 10 ), 0, 4, mod( l_value , 10 ) ) ), 'YYYY' ), 'YTH' ), 2 ) as value
from dual
Replace l_value with appropriate, hmmm, value. Should cover any numbers.