Error Handling when converting text to dates - sql

Lets says I have a column which has text and most of them are in a particular format which allows me to scrape out the date part. However, some of the texts does not have dates and I want it to return NULL rather than scraping it. How would I go about doing this in Redshift (SQL)?
Current Output:
CAST(REPLACE(SUBSTRING(c."name",3,9),'.','-') AS DATE)
Some fields are like the below and I need the code to return a null when it cannot convert the substring to a date datetype
Example:
Error:

You can use pattern matching and case + when for such cases
select case
when c."name" similar to '%\\d{2}.\\d{2}.\\d{2}%'
then CAST(REPLACE(SUBSTRING(c."name", 3, 9), '.', '-') AS DATE)
else null
end as cast_date;

Related

Redshift can't convert a string to a date, tried multiple functions

I have a table with a field called ADATE, it is a VARCHAR(16) and the values are like so: 2019-10-22-09:00.
I am trying to convert this do a DATE type but cannot get this to work.
I have tried:
1
TO_DATE(ADATE, 'YYYY-MM-DD')
Can't cast database type date to string
2
TO_DATE(LEFT(ADATE, 10), 'YYYY-MM-DD')
Can't cast database type date to string
3
TO_DATE(TRUNC(ADATE), 'YYYY-MM-DD')
XX000: Invalid digit, Value '-', Pos 4, Type: Decimal
4
CAST(ADATE AS DATE)
Error converting text to date
5
CAST(LEFT(ADATE, 10) AS DATE)
Error converting text to date
6
CAST(TRUNC(ADATE) AS DATE)
Error converting numeric to date
The issue was the data containing blanks (not Nulls) so the error was around them.
I resolved this by using the following code:
TO_DATE(LEFT(CASE WHEN adate = '' THEN NULL ELSE adate END, 10), 'YYYY-MM-DD') adate
Clearly, you have bad date string values -- which is why the value should be stored as a date to begin with.
I don't think Redshift has a way of validating the date before attempting the comparison, or of avoiding an error. But you can use case and regular expressions to see if the value is reasonable. This might help:
(case when left(adate, 10) ~ '^(19|20)[0-9][0-9]-[0-1][0-9]-[0-3][0-9]$'
then to_date(left(adate, 10), 'YYYY-MM-DD')
end)
This is not precise . . . you can make it more complex so month 19 is not permitted (for instance), but it is likely to catch the errors.

SQL Null dates return 1900-01-01

Here is part of my query:
IsNull(CONVERT(date, V_CONSTAT_ACTUAL_DATES.ID50), '') AS 'actualFinish'
V_CONSTAT_ACTUAL_DATES.ID50 is a NULL and is a datetime column. So the results I get is 1900-01-01, what I am trying to do is return nothing just ' ' How would I accomplish this?
The mixing of types you have now is definitely a problem.
If you want to display an empty string for a null date you need convert the date into a short date time string not a date. You can use the convert function to do that. The last parameter accepts a style code so you can have it display just the date part.
COALESCE(CONVERT(varchar(8), V_CONSTAT_ACTUAL_DATES.ID50, 101), '') AS 'actualFinish'
This will display the date in mm/dd/yy format if the column is not null, or an empty string if it is.
To see more about date to string conversions go to https://msdn.microsoft.com/en-us/library/ms187928.aspx.
Rather than ISNULL or COALESCE try using a CASE statement -
SELECT CASE WHEN date IS NULL THEN '' ELSE CONVERT(date, V_CONSTAT_ACTUAL_DATES.ID50) END
Simple ISNULL Nested CAST function can remove 1900-1-1 value if data is NULL
ISNULL(CAST(CAST(<<DateColumn>> AS DATE) AS Varchar),' ') [<<Date Column Name>>]

Function to evaluate valid and invalid dates

I am using SQL Server 2008
I receive data in a couple of formats. Dates are varchar(10)
For example:
1> 951116 = YYMMDD
2> 122487 = MMDDYY
There exists rows with blank values or some rows have some text in it.
I want to check if it is a date and convert it, else it can be null.
I have been using the following code but it only enables me to convert the date as in the 1st example and throws an error in the second one.
create view v2 as
SELECT name
,CASE WHEN LEN(DOB) < 6 THEN '' ELSE CONVERT(VARCHAR,
CAST(CAST('19' + SUBSTRING(DOB, 5, 2) + SUBSTRING(DOB, 1, 2) + SUBSTRING(DOB, 3, 2) AS VARCHAR(10)) AS DATE), 110) END AS OWNR_DOB
FROM customer
I want to write a function and get it to YYYYMMDD format.
A simple function just to convert the YYMMDD format to YYYYMMDD and treat the other values as invalid or null can be a start too.
Any help is appreciated.

Pull numbers out of a decimal

Okay so, I have a column that looks something like this:
20140813000000000
It is displaying a date, in the format of decimal(17,0), but I need to take the first 8 characters out of it to convert it to a date so it can be used. I've tried casting and converting and substring but everything leads to an arithmetic overflow. Any help on getting that date out?
Example of what I am using and the error:
CAST(SUBSTRING(CAST([tblDate] as varchar),1,8) as Date)
Conversion failed when converting date and/or time from character string.
I got it working, I added a case to filter out the 0's to NULL before casting it as a date:
Select
CAST(CASE
WHEN SUBSTRING(CAST([tblDate] as varchar),1,8) = 0 THEN NULL
ELSE SUBSTRING(CAST([tblDate] as varchar),1,8)
END as DATE)
Great that you found a solution to your own problem, but note that this won't work if you ever have values like 00000000000000001 in your table as this will be converted to 1, pass the first test in your CASE statement and then throw an exception as 1 won't CAST to DATE.
This is more long-winded, but safer... (full example included):
DECLARE #TestTable TABLE ([tblDate] NUMERIC(17,0));
INSERT INTO #TestTable VALUES(00000000000000001); --Edge case
INSERT INTO #TestTable VALUES(20140831000000001); --Value to parse
SELECT
CASE
WHEN SUBSTRING(REPLACE(RIGHT('00000000000000000' + CAST([tblDate] AS VARCHAR(17)), 17), SPACE(1), '0'), 1, 8) = '00000000' THEN NULL
ELSE SUBSTRING(CAST([tblDate] AS VARCHAR(17)), 1, 8)
END
FROM
#TestTable;
Returns:
NULL
2014-08-31
Your answer would throw an exception for the first value.
If you are sure your data will ALWAYS either be all zeroes or contain a date to be parsed then fine...

Convert String to date in select statement

I have a column which contains data but the problem is that this column has data type of varchar(50) and it has to be this due to some reasons,now what i want to do is while selecting data from table , i want to treat this column as date so that i can use it in where clause. i am using the code below for converting it yo date , but it converts some values and then gives an error
this is my sample data
8/1/2002
6/9/2001
14/9/2001
26/7/2001
14/12/2001
21/1/2002
29/4/2001
7/5/2001
9/11/2001
16/7/2001
select CONVERT(date,sowingDate,103) from tblAgriculture_staging
I have tried which differnt version of date format e.g 103,105 etc
but still it converts some values but error comes on some values and query execution stops
Try this:
SET DATEFORMAT dmy;
select case when isdate(sowingDate) = 1 then CONVERT(date,sowingDate,103) end [date] from tblAgriculture_staging
or (if you are using sql 2012)
SET DATEFORMAT dmy;
select case when TRY_CONVERT(date, sowingDate) IS NOT NULL then CONVERT(date,sowingDate,103) end [date] from tblAgriculture_staging
but this solution hides (convert to NULL) all dates that are wrong. You can reverse the condition first and find/fix all rows with incorrect date (i.e. 31/02/2013) and then use this queries to show only valid dates
SQLFiddle
but it converts some values and then gives an error this is my sample
data
because some data are in invalid format or contains incorrect symbols.
Try this:
select CONVERT(date,ltrim(rtrim(sowingDate)), 103) from tblAgriculture_staging
or examine your values:
select ISDATE(sowingDate) as IsDate, sowingDate, CASE WHEN ISDATE(sowingDate)=1 THEN CONVERT(date,ltrim(rtrim(sowingDate)), 103) ELSE NULL END from tblAgriculture_staging
This is slightly crappy, but so is storing dates as varchar.
this is code that has worked for me in the past where i had some dates with 4 digit years and some with 2 digit years.
where (TRY_CONVERT(Datetime2,LTRIM(RTRIM([INVC DTE])),1)>=#From
AND TRY_CONVERT(Datetime2,LTRIM(RTRIM([INVC DTE])),1)<=#To)
OR (TRY_CONVERT(Datetime2,LTRIM(RTRIM([INVC DTE])),101)>=#From
AND TRY_CONVERT(Datetime2,LTRIM(RTRIM([INVC DTE])),101)<=#To)
SQL Server 2012 + Only
This assumes you have cleaned up anything that actually just isn't a date...
This will return all the dates that are not actually dates.
select sowingDate from tblAgriculture_staging where isdate(sowingDate)=0