Retrieve Year from string date in Oracle SQL - sql

I have the following column of dates:
EXPIRY_DAT
31-Oct-17
31-Oct-17
18-Nov-18 12:11:10
31-Dec-12
31-Oct-17
31-Oct-17
18-Nov-18 12:11:10
31-Dec-12
31-Oct-17
31-Oct-17
20-Jul-18 19:20:33
31-Oct-18
31-Oct-18
11-Aug-19 21:52:56
31-Dec-12
.
.
.
I would like to retrieve the year from these series in the form YYYY.
I already tried using the following line of SQL code:
TO_DATE(TO_CHAR(EXPIRY_DAT, 'DD-MON-YY HH:MI:SS'), 'YYYY'
although it returns me the error message:
ORA-01830: date format picture ends before converting entire input string

If all your dates are in one of the formats you showed, this could be enough:
-- test case
with dateTable(EXPIRY_DAT) as (
select '31-Oct-17' from dual union all
select '31-Oct-17' from dual union all
select '18-Nov-18 12:11:10' from dual union all
select '31-Dec-12' from dual union all
select '31-Oct-17' from dual union all
select '31-Oct-17' from dual union all
select '18-Nov-18 12:11:10' from dual union all
select '31-Dec-12' from dual union all
select '31-Oct-17' from dual union all
select '31-Oct-17' from dual union all
select '20-Jul-18 19:20:33' from dual union all
select '31-Oct-18' from dual union all
select '31-Oct-18' from dual union all
select '11-Aug-19 21:52:56' from dual union all
select '31-Dec-12' from dual
)
-- query
select to_char(to_date(substr(EXPIRY_DAT, 1, 9), 'dd-mon-yy'), 'yyyy')
from dateTable

Use:
select extract(year from TO_DATE(SUBSTR(EXPIRY_DAT,1,9),'DD-Mon-YY')
from your_table

Related

Monthly statistics. ORA-01722: Invalid number

I use two choices to make monthly statistics. The first select selects the appropriate data, and then carefully counts the monthly statistics.
First select:
SELECT
TO_CHAR (ZDZDATETIME, 'RRRR-MM-DD') AS DA,
ID,
MAX (DAYRF) AS DAYRF
FROM
JC_T_QXJYJCSJ
WHERE
ID = 'G2001'
GROUP BY
TO_CHAR (ZDZDATETIME, 'RRRR-MM-DD'),
ID
ORDER BY
ID,
TO_CHAR (ZDZDATETIME, 'RRRR-MM-DD')
the result:
result
the final code:
SELECT
TO_CHAR (DA, 'RRRR-MM') AS DA1,
SUM (DAYRF)FROM(
SELECT
TO_CHAR (ZDZDATETIME, 'RRRR-MM-DD') AS DA,
ID,
MAX (DAYRF) AS DAYRF
FROM
JC_T_QXJYJCSJ
WHERE
ID = 'G2001'
GROUP BY
TO_CHAR (ZDZDATETIME, 'RRRR-MM-DD'),
ID
ORDER BY
ID,
TO_CHAR (ZDZDATETIME, 'RRRR-MM-DD')
) GROUP BY
TO_CHAR (DA, 'RRRR-MM');
Always prompt me for invalid numbers
I think the ID=‘G2001’ sentence has a problem, so I tried to change it to other ID='XXX' and it will run successfully. I don’t know if an error other than code has occurred.
Your question did not reveal much information about your issue.
I tried to convert your question into one problem statement and resolved the same using following query.
WITH DATAA(ID, DAYRF, DATE1) AS
(
SELECT 1, 10, DATE '2019-06-22' FROM DUAL UNION ALL
SELECT 1, 9 , DATE '2019-06-22' FROM DUAL UNION ALL
SELECT 1, 5, DATE '2019-06-22' FROM DUAL UNION ALL
SELECT 2, 20, DATE '2019-06-22' FROM DUAL UNION ALL
SELECT 2, 15, DATE '2019-06-22' FROM DUAL UNION ALL
SELECT 2, 12, DATE '2019-06-22' FROM DUAL UNION ALL
SELECT 3, 5, DATE '2019-06-22' FROM DUAL UNION ALL
SELECT 3, 30, DATE '2019-06-22' FROM DUAL UNION ALL
SELECT 1, 20, DATE '2019-06-23' FROM DUAL UNION ALL
SELECT 1, 29 , DATE '2019-06-23' FROM DUAL UNION ALL
SELECT 1, 15, DATE '2019-06-23' FROM DUAL UNION ALL
SELECT 2, 40, DATE '2019-06-23' FROM DUAL UNION ALL
SELECT 2, 45, DATE '2019-06-23' FROM DUAL UNION ALL
SELECT 2, 32, DATE '2019-06-23' FROM DUAL UNION ALL
SELECT 3, 19, DATE '2019-06-23' FROM DUAL UNION ALL
SELECT 3, 1, DATE '2019-06-23' FROM DUAL
)
SELECT
DATE1,
SUM(MAX_DAYRF)
FROM
(
SELECT
DATE1,
ID,
MAX(DAYRF) AS MAX_DAYRF
FROM
DATAA
GROUP BY
DATE1,
ID
)
GROUP BY
DATE1;
Ouptut
Fiddle Demo
Cheers!!

current year's date of birth using oracle sql

Trying to get birth day date in the current year.
For an example if DOB=19800925, birth day in the current year is 20180925
(note: we should not just replace the year because of the leap year DOB (ex: 20000229))
with tmp_dob as
(
select '19900101' Birthday from dual union all
select '19901231' Birthday from dual union all
select '20040229' Birthday from dual union all
select '20041231' Birthday from dual union all
select '20171231' Birthday from dual union all
select '20051231' Birthday from dual
)
select Birthday,add_months(to_date(Birthday,'YYYYMMDD'),(trunc(months_between(sysdate ,to_date(Birthday,'YYYYMMDD'))/12)) * 12) current_year_dob
from tmp_dob;
This logic should work:
with tmp_dob as (
select to_date('19900101', 'YYYYMMDD') as Birthday from dual union all
select to_date('19901231', 'YYYYMMDD') Birthday from dual union all
select to_date('20040229', 'YYYYMMDD') Birthday from dual union all
select to_date('20041231', 'YYYYMMDD') Birthday from dual union all
select to_date('20171231', 'YYYYMMDD') Birthday from dual union all
select to_date('20051231', 'YYYYMMDD') Birthday from dual
)
select Birthday,
add_months(birthday, 12 * (extract(year from sysdate) - extract(year from birthday)))
from tmp_dob;
Add months approach works, but you'll get 2/28 for the leap-day birthdays. If you want that to be 03/01, or to be configurable, use a case to detect the condition and override:
with tmp_dob as (
select to_date('19900101', 'YYYYMMDD') as Birthday from dual union all
select to_date('19901231', 'YYYYMMDD') Birthday from dual union all
select to_date('20040229', 'YYYYMMDD') Birthday from dual union all
select to_date('20041231', 'YYYYMMDD') Birthday from dual union all
select to_date('20171231', 'YYYYMMDD') Birthday from dual union all
select to_date('20051231', 'YYYYMMDD') Birthday from dual
)
select Birthday,
case
when
to_date(extract(year from sysdate) || '1231', 'YYYYMMDD') -
to_date(extract(year from sysdate) || '0101', 'YYYYMMDD') < 365
and to_char(birthday, 'MMDD') = '0229' then
to_date(extract(year from sysdate) || '0301', 'YYYYMMDD')
else
add_months(birthday, 12 * (extract(year from sysdate) - extract(year from birthday)))
end as bd_this_year
from tmp_dob;
Results:
BIRTHDAY BD_THIS_YEAR
1/1/1990 1/1/2018
12/31/1990 12/31/2018
2/29/2004 3/1/2018
12/31/2004 12/31/2018
12/31/2017 12/31/2018
12/31/2005 12/31/2018
Consider making a function to do the same thing - your query will be easier to read.
I thought about using an approach of strings since the birthdays you are using are on strings too.
I use the BigQuery Syntax but there should be similar functions in every SQL.
with tmp_dob as
(
select '19900101' Birthday from dual union all
select '19901231' Birthday from dual union all
select '20040229' Birthday from dual union all
select '20041231' Birthday from dual union all
select '20171231' Birthday from dual union all
select '20051231' Birthday from dual
)
select Birthday,
CASE WHEN MOD(CAST(SUBSTR(Birthday,1,4) AS INT64), 4) = 0 AND SUBSTR(Birthday,5,8) = '0229'
THEN CONCAT(CAST(EXTRACT(YEAR FROM CURRENT_DATE) AS STRING), '0228')
ELSE CONCAT(CAST(EXTRACT(YEAR FROM CURRENT_DATE) AS STRING), SUBSTR(Birthday,5,8)) END AS bd
from tmp_dob;

Converting Day of the Year to a date when some date formats have DDYYYY and some have DDDYYYY in oracle

So I am trying to convert some Day of the Year dates to Date format. The problem is some day of the year dates are in DDYYYY format for days under 100 and DDDYYYY format for days 100 and over. I have tried the following but still receive a "day of year must be between 1 and 365 (366 for leap year)" error:
select CASE when data_Date >= 999999
then to_date(data_date, 'DDDYYYY')
when data_Date >= 99999
then to_date(data_Date, 'DDYYYY')
else to_date(data_date, 'DYYYY')
END as DATA_DATE_CONVERTED
from table;
Thanks in advance
Sample Data is as follows:
Data_date (being passed in as a varchar2)
1072015
12017
612014
672013
72017
1112018
The last 4 digit is the year. Use LPAD to put leading zeroes on DAY
select to_date( lpad(dayyear, 7, '0'),'DDDYYYY')
from table;
sqlfiddle
How about this:
with demo (data_date) as
( select 1072015 from dual union all
select 12017 from dual union all
select 612014 from dual union all
select 672013 from dual union all
select 72017 from dual union all
select 1112018 from dual )
select data_date
, to_char(data_date,'0000000')
, to_date(to_char(data_date,'0000000'),'DDDYYYY') as data_date_converted
from demo
You can also put a dash (-) between.
with demo (data_date) as
( select 1072015 from dual union all
select 12017 from dual union all
select 612014 from dual union all
select 672013 from dual union all
select 72017 from dual union all
select 1112018 from dual )
select data_date, TO_DATE(SUBSTR(data_date, 1, length(data_date)-4)||'-'||SUBSTR(data_date, -4, 4), 'DDD-YYYY')
from demo;

Big "union select all" construct - how to get rid of `Too many Contexts of Relation-Procedure-Views. Maximum allowed is 255`

I've a big SQL statement that looks similar to the one below.
As soon as there are more than 128 entries combined with union all, then I get this error: Too many Contexts of Relation-Procedure-Views. Maximum allowed is 255
How can I reformulate the query to get rid of the error?
There is no way to add this data to the database (it's in a script that does sanity checking of the database; the script has read-access only as the database can be in read-only mode).
Of the columns below:
id and identifier have distinct values in each row
id is the numeric ID and it have gaps that are known in advance
identifier is an alphanumeric name (so unlike the below query, you cannot generate identifier from id)
usage has two string values which are valid for certain groups of id (so I could put them in a separate union all construct)
comment has about 20 distinct string values which are valid for certain groups of id (so I could put them in a separate union all construct as well)
A query that reproduces this:
-- 20161024 - Too many Contexts of Relation-Procedure-Views. Maximum allowed is 255
with parameters as
(
select 1001 as id
, '1001' as usage
, 'PP_1001' as identifier
, '1001' as comment
from rdb$database
union all select 1002,'1002','PP_1002','1002' from rdb$database
union all select 1003,'1003','PP_1003','1003' from rdb$database
union all select 1004,'1004','PP_1004','1004' from rdb$database
union all select 1005,'1005','PP_1005','1005' from rdb$database
union all select 1006,'1006','PP_1006','1006' from rdb$database
union all select 1007,'1007','PP_1007','1007' from rdb$database
union all select 1008,'1008','PP_1008','1008' from rdb$database
union all select 1009,'1009','PP_1009','1009' from rdb$database
union all select 1010,'1010','PP_1010','1010' from rdb$database
union all select 1011,'1011','PP_1011','1011' from rdb$database
union all select 1012,'1012','PP_1012','1012' from rdb$database
union all select 1013,'1013','PP_1013','1013' from rdb$database
union all select 1014,'1014','PP_1014','1014' from rdb$database
union all select 1015,'1015','PP_1015','1015' from rdb$database
union all select 1016,'1016','PP_1016','1016' from rdb$database
union all select 1017,'1017','PP_1017','1017' from rdb$database
union all select 1018,'1018','PP_1018','1018' from rdb$database
union all select 1019,'1019','PP_1019','1019' from rdb$database
union all select 1020,'1020','PP_1020','1020' from rdb$database
union all select 1021,'1021','PP_1021','1021' from rdb$database
union all select 1022,'1022','PP_1022','1022' from rdb$database
union all select 1023,'1023','PP_1023','1023' from rdb$database
union all select 1024,'1024','PP_1024','1024' from rdb$database
union all select 1025,'1025','PP_1025','1025' from rdb$database
union all select 1026,'1026','PP_1026','1026' from rdb$database
union all select 1027,'1027','PP_1027','1027' from rdb$database
union all select 1028,'1028','PP_1028','1028' from rdb$database
union all select 1029,'1029','PP_1029','1029' from rdb$database
union all select 1030,'1030','PP_1030','1030' from rdb$database
union all select 1031,'1031','PP_1031','1031' from rdb$database
union all select 1032,'1032','PP_1032','1032' from rdb$database
union all select 1033,'1033','PP_1033','1033' from rdb$database
union all select 1034,'1034','PP_1034','1034' from rdb$database
union all select 1035,'1035','PP_1035','1035' from rdb$database
union all select 1036,'1036','PP_1036','1036' from rdb$database
union all select 1037,'1037','PP_1037','1037' from rdb$database
union all select 1038,'1038','PP_1038','1038' from rdb$database
union all select 1039,'1039','PP_1039','1039' from rdb$database
union all select 1040,'1040','PP_1040','1040' from rdb$database
union all select 1041,'1041','PP_1041','1041' from rdb$database
union all select 1042,'1042','PP_1042','1042' from rdb$database
union all select 1043,'1043','PP_1043','1043' from rdb$database
union all select 1044,'1044','PP_1044','1044' from rdb$database
union all select 1045,'1045','PP_1045','1045' from rdb$database
union all select 1046,'1046','PP_1046','1046' from rdb$database
union all select 1047,'1047','PP_1047','1047' from rdb$database
union all select 1048,'1048','PP_1048','1048' from rdb$database
union all select 1049,'1049','PP_1049','1049' from rdb$database
union all select 1050,'1050','PP_1050','1050' from rdb$database
union all select 1051,'1051','PP_1051','1051' from rdb$database
union all select 1052,'1052','PP_1052','1052' from rdb$database
union all select 1053,'1053','PP_1053','1053' from rdb$database
union all select 1054,'1054','PP_1054','1054' from rdb$database
union all select 1055,'1055','PP_1055','1055' from rdb$database
union all select 1056,'1056','PP_1056','1056' from rdb$database
union all select 1057,'1057','PP_1057','1057' from rdb$database
union all select 1058,'1058','PP_1058','1058' from rdb$database
union all select 1059,'1059','PP_1059','1059' from rdb$database
union all select 1060,'1060','PP_1060','1060' from rdb$database
union all select 1061,'1061','PP_1061','1061' from rdb$database
union all select 1062,'1062','PP_1062','1062' from rdb$database
union all select 1063,'1063','PP_1063','1063' from rdb$database
union all select 1064,'1064','PP_1064','1064' from rdb$database
union all select 1065,'1065','PP_1065','1065' from rdb$database
union all select 1066,'1066','PP_1066','1066' from rdb$database
union all select 1067,'1067','PP_1067','1067' from rdb$database
union all select 1068,'1068','PP_1068','1068' from rdb$database
union all select 1069,'1069','PP_1069','1069' from rdb$database
union all select 1070,'1070','PP_1070','1070' from rdb$database
union all select 1071,'1071','PP_1071','1071' from rdb$database
union all select 1072,'1072','PP_1072','1072' from rdb$database
union all select 1073,'1073','PP_1073','1073' from rdb$database
union all select 1074,'1074','PP_1074','1074' from rdb$database
union all select 1075,'1075','PP_1075','1075' from rdb$database
union all select 1076,'1076','PP_1076','1076' from rdb$database
union all select 1077,'1077','PP_1077','1077' from rdb$database
union all select 1078,'1078','PP_1078','1078' from rdb$database
union all select 1079,'1079','PP_1079','1079' from rdb$database
union all select 1080,'1080','PP_1080','1080' from rdb$database
union all select 1081,'1081','PP_1081','1081' from rdb$database
union all select 1082,'1082','PP_1082','1082' from rdb$database
union all select 1083,'1083','PP_1083','1083' from rdb$database
union all select 1084,'1084','PP_1084','1084' from rdb$database
union all select 1085,'1085','PP_1085','1085' from rdb$database
union all select 1086,'1086','PP_1086','1086' from rdb$database
union all select 1087,'1087','PP_1087','1087' from rdb$database
union all select 1088,'1088','PP_1088','1088' from rdb$database
union all select 1089,'1089','PP_1089','1089' from rdb$database
union all select 1090,'1090','PP_1090','1090' from rdb$database
union all select 1091,'1091','PP_1091','1091' from rdb$database
union all select 1092,'1092','PP_1092','1092' from rdb$database
union all select 1093,'1093','PP_1093','1093' from rdb$database
union all select 1094,'1094','PP_1094','1094' from rdb$database
union all select 1095,'1095','PP_1095','1095' from rdb$database
union all select 1096,'1096','PP_1096','1096' from rdb$database
union all select 1097,'1097','PP_1097','1097' from rdb$database
union all select 1098,'1098','PP_1098','1098' from rdb$database
union all select 1099,'1099','PP_1099','1099' from rdb$database
union all select 1100,'1100','PP_1100','1100' from rdb$database
union all select 1101,'1101','PP_1101','1101' from rdb$database
union all select 1102,'1102','PP_1102','1102' from rdb$database
union all select 1103,'1103','PP_1103','1103' from rdb$database
union all select 1104,'1104','PP_1104','1104' from rdb$database
union all select 1105,'1105','PP_1105','1105' from rdb$database
union all select 1106,'1106','PP_1106','1106' from rdb$database
union all select 1107,'1107','PP_1107','1107' from rdb$database
union all select 1108,'1108','PP_1108','1108' from rdb$database
union all select 1109,'1109','PP_1109','1109' from rdb$database
union all select 1110,'1110','PP_1110','1110' from rdb$database
union all select 1111,'1111','PP_1111','1111' from rdb$database
union all select 1112,'1112','PP_1112','1112' from rdb$database
union all select 1113,'1113','PP_1113','1113' from rdb$database
union all select 1114,'1114','PP_1114','1114' from rdb$database
union all select 1115,'1115','PP_1115','1115' from rdb$database
union all select 1116,'1116','PP_1116','1116' from rdb$database
union all select 1117,'1117','PP_1117','1117' from rdb$database
union all select 1118,'1118','PP_1118','1118' from rdb$database
union all select 1119,'1119','PP_1119','1119' from rdb$database
union all select 1120,'1120','PP_1120','1120' from rdb$database
union all select 1121,'1121','PP_1121','1121' from rdb$database
union all select 1122,'1122','PP_1122','1122' from rdb$database
union all select 1123,'1123','PP_1123','1123' from rdb$database
union all select 1124,'1124','PP_1124','1124' from rdb$database
union all select 1125,'1125','PP_1125','1125' from rdb$database
union all select 1126,'1126','PP_1126','1126' from rdb$database
union all select 1127,'1127','PP_1127','1127' from rdb$database
union all select 1128,'1128','PP_1128','1128' from rdb$database
--union all select 1129,'1129','PP_1129','1129' from rdb$database
)
select parameters.id
, parameters.usage
, parameters.identifier
, parameters.comment
from parameters
where parameters.id <> -1
order by parameters.id
A construct like the one below should get me going.
The params is a table in the database that needs to be compared to the artificial parameters table that is sparsely filled.
Techniques used:
recursive query to generate a sequence of ID values in IDs
case constructs to fill the columns
In the actual query there will be a case with when and then for all validId values and smaller case constructs for the columns needing less values.
Query without error:
select parameters.id
, parameters.usage
, parameters.identifier
, parameters.comment
, params.ID param_id
, params.AVALUE
, params.DESCRIPTION
from
(
with recursive IDs as
(
select 0 as ID from rdb$database
union all
select 1 + ID from IDs where ID < 1000
)
select
ID
, case
when ((ID = 999) or (ID between 0 and 130))
then 1
else 0
end as validId
, case
when ID in
(
3,
12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
41, 42, 46, 47,
50, 51, 52, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
70, 71, 72, 79,
80, 83, 84, 85, 86, 87, 88, 89,
90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
120, 121, 122, 123, 124, 125, 126, 127, 129,
999
)
then 'used'
else 'unused'
end as usage
, '' as identifier
, '' as comment
from
IDs
) parameters
full outer join params
on params.ID = parameters.id
where parameters.validId = 1
order by params.id, parameters.id

How do update a date column by changing only the year and not the day or month using PLSQL?

I have a database table containing credit card records. One of the fields is a Date field. I would like to update this field by changing the year portion of the date to 2011 if the year is less than 2010. From what i have found, PLSQL has functions for time and months but nothing to do with years (to my knowledge).
This shows how to
with cc as(
select to_date('12-jan-1999') as cdate from dual union all
select to_date('12-jan-1921') as cdate from dual union all
select to_date('12-jan-1900') as cdate from dual union all
select to_date('12-jan-2000') as cdate from dual union all
select to_date('12-jan-2010') as cdate from dual
)
select to_date( to_char(cdate,'DD-MON') ||'-2011','DD-MON-YYYY')
from cc
where cdate < to_date('01-JAN-2010','DD-MON-YYYY')
/
1 year = 12 months, so subtract 12 months:
select add_months(sysdate,-12) from dual
Here's how to do it so it works with leap years using add_months.
with cc as(
select to_date('12-jan-1999','dd-mon-yyyy') as cdate from dual union all
select to_date('12-jan-1921','dd-mon-yyyy') as cdate from dual union all
select to_date('29-feb-1904','dd-mon-yyyy') as cdate from dual union all
select to_date('12-jan-2000','dd-mon-yyyy') as cdate from dual union all
select to_date('12-jan-2010','dd-mon-yyyy') as cdate from dual
)
select add_months(cdate,(2011 - extract( year from cdate)) * 12)
from cc
where cdate < to_date('01-JAN-2010','DD-MON-YYYY');