how to sum up minutes and seconds ?in oracle - sql

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

Related

Validation of first 6 digits in a SQL query in Oracle SQL developer

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'))
;

Convert Oracle Date into RFC 3339 Format

I have a date field in oracle which returns
17-APR-19 12:00:00 AM
I also have a time column (VARCHAR) which returns HHMM in Military
1810
I'd like to combine these two fields to create a timestamp that is formatted to RFC 3339 standards. Preferable like this.
2019-04-17T18:10:00Z
I can convert a timestamp into the correct time using this:
SELECT
TO_CHAR(
SYSTIMESTAMP AT TIME ZONE 'UTC',
'yyyy-mm-dd"T"hh24:mi:ss"Z"'
)
FROM dual;
Is there a way to convert my date and time field into this timestamp format? The time on the date field is incorrect and needs to be replaced by the time field.
You can TRUNCate your date back to midnight and then use NUMTODSINTERVAL to add hours and minutes to it to get the correct time component:
Oracle Setup:
CREATE TABLE your_table ( your_date_column, your_time_column ) AS
SELECT DATE '2019-04-17', '1810' FROM DUAL
Query:
SELECT TO_CHAR(
TRUNC( your_date_column )
+ NUMTODSINTERVAL( SUBSTR( your_time_column, 1, 2 ), 'HOUR' )
+ NUMTODSINTERVAL( SUBSTR( your_time_column, 3, 2 ), 'MINUTE' ),
'YYYY-MM-DD"T"HH24:MI:SS"Z"'
) AS combined_date_time
FROM your_table
Output:
| COMBINED_DATE_TIME |
| :------------------- |
| 2019-04-17T18:10:00Z |
db<>fiddle here
If you want the value as a TIMESTAMP WITH TIME ZONE then:
SELECT CAST(
TRUNC( your_date_column )
+ NUMTODSINTERVAL( SUBSTR( your_time_column, 1, 2 ), 'HOUR' )
+ NUMTODSINTERVAL( SUBSTR( your_time_column, 3, 2 ), 'MINUTE' )
AS TIMESTAMP
) AT TIME ZONE 'UTC' AS combined_date_time
FROM your_table
Just do a bit of string concatenation
to_char( your_date, 'yyyy-mm-dd' ) ||
'T' ||
substr( your_time, 1, 2 ) ||
':' ||
substr( your_time, 3, 2 ) ||
':00Z'
assuming that your_time is always 4 characters long (i.e. 2 AM is represented as the string '0200' rather than '200'). This also assumes that the seconds will always be '00'.
You can achieve this by converting your_number into minutes and add it to your date, then cast it to timestamp as following:
SELECT CAST(
your_date +
(FLOOR(YOUR_TIME/100)*60 + MOD(YOUR_TIME,100)) / 1440
AS TIMESTAMP
) AT TIME ZONE 'UTC' AS YOUR_TIME_STAMP
FROM your_table;
Cheers!!

Modifying a query to work without requiring NLS_DATE_FORMAT to be set

I the following query:
SELECT
trunc(estimatedenddate,'hh') AS reg_date,
COUNT(*)
FROM
(
SELECT
attr_value,
TO_DATE( (DATE '1970-01-01' + (1 / 24 / 60 / 60 / 1000) * attr_value),'yyyy-mm-dd HH24:mi:ss') AS estimatedenddate
FROM
attr
WHERE
attr_name = 'createTimestamp'
)
WHERE
estimatedenddate > TO_DATE('01/JUN/2018','dd/mon/yyyy')
GROUP BY
trunc(estimatedenddate,'hh')
ORDER BY
reg_date DESC;
It works when I set the NLS_DATE_FORMAT. See dbfiddle.
However if I do not set the NLS_DATE_FORMAT, the query doesn't produce any results. See dbfiddle
How can I modify this query such that it works without setting the NLS_DATE_FORMAT?
TO_DATE( date_string, format_model ) takes a string for the first argument but you are passing a DATE data type which Oracle will try to be helpful and implicitly convert to the expected string data type using its default format model; so your inner query is effectively:
SELECT attr_value,
TO_DATE(
TO_CHAR(
DATE '1970-01-01' + (1 / 24 / 60 / 60 / 1000) * attr_value,
(SELECT value FROM NLS_SESSION_PARAMETERS WHERE parameter = 'NLS_DATE_FORMAT')
),
'yyyy-mm-dd HH24:mi:ss'
) AS estimatedenddate
FROM attr
WHERE attr_name = 'createTimestamp'
Instead you can just remove the TO_DATE() function:
SELECT trunc(estimatedenddate,'hh') AS reg_date,
COUNT(*)
FROM (
SELECT DATE '1970-01-01' + (1 / 24 / 60 / 60 / 1000) * attr_value AS estimatedenddate
FROM attr
WHERE attr_name = 'createTimestamp'
)
WHERE estimatedenddate > DATE '2018-06-01'
GROUP BY trunc(estimatedenddate,'hh')
ORDER BY reg_date DESC;

Convert DB2 SQL Decimal to DATE

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).

Help with Sql query for comparing string(HH24MI) to date

We have a configuration table as shown below that stores the start time and the duration.
If the start time is 9:20 pm (3rd one ) add the duration then the time becomes 9:35.
I have to find out if the current time is in between any of the values.
I have to return the output based on the start_time and duration. i.e current time should be between start_time and the start_time + duration. (between 09:20 and and 09:35)
Can you please help me with the sql query or is it better if we go with sql function?
Start_time, duration(minutes) output
1108 5 2
1054 100 5
2120 15 8
I'm not a fan of storing dates and times in VARCHAR2 columns. START_TIME should really be a DATE or a TIMESTAMP column.
That said, you can do something like
with x as (
select '1108' start_time, 5 duration, 2 output from dual
union all
select '1054', 100, 5 from dual
union all
select '2120', 15, 8 from dual
)
select *
from (
select to_date(
to_char(sysdate,'YYYY-MM-DD') || ' ' ||
start_time,
'YYYY-MM-DD HH24MI' ) start_date,
to_date(
to_char(sysdate,'YYYY-MM-DD') || ' ' ||
start_time,
'YYYY-MM-DD HH24MI' ) + duration/24/60 end_date
from x)
where sysdate between start_date and end_date
The following selects all rows where sysdate is within the Start_Time and Start_Time + duration (EDITed as per comment from OP):
SELECT (TRUNC ( SYSDATE ) + TO_NUMBER ( SUBSTR ( Start_Time, 0, 2 ) ) / 24.0 + TO_NUMBER ( SUBSTR ( Start_Time, 3 ) ) / (24.0 * 60.0)) start_date, (TRUNC ( SYSDATE ) + TO_NUMBER ( SUBSTR ( Start_Time, 0, 2 ) ) / 24.0 + TO_NUMBER ( SUBSTR ( Start_Time, 3 ) ) / (24.0 * 60.0) + TO_NUMBER (duration)) end_date FROM configtable;