# getting month and day from date # - sql

I have a table in which there is a column, ci_birthday. The column is declared as nvarchar(50), the format is mm-dd-yyyy. The data in the table is like this:
CI_BIRTHDAY
-----------
07/14/1956
NULL
NULL
11/01/1969
08/15/1955
07/08/1965
NULL
NULL
09/20/1936
NULL
NULL
NULL
NULL
0/0/0
NULL
NULL
NULL
NULL
NULL
0/0/0
NULL
NULL
1/29/1940
NULL
0/0/0
NULL
NULL
NULL
NULL
08/11/1949
I want the output from that column is only month and day, like
09/20
0/0
1/29
08/11
0/0

I accept my solution is a very bad way of solving this but if the date is not stored in a date format (in this case its a string), then you can do something like this:
DECLARE #Date varchar(15) = '11/01/1969'
SELECT SUBSTRING(#Date, 1,LEN(#Date) - PATINDEX('%/%',REVERSE(#Date)))

Just to show how to cast this very messy data into dates after checking it's safe to do so:
SET DATEFORMAT mdy;
WITH Dates
AS ( SELECT '07/14/1956' AS DateStr
UNION
SELECT '11/01/1969'
UNION
SELECT '08/15/1955'
UNION
SELECT '07/08/1965'
UNION
SELECT '09/20/1936'
UNION
SELECT '0/0/0'
UNION
SELECT NULL
UNION
SELECT '1/29/1940'
)
SELECT CASE WHEN ISDATE(DateStr) = 1 THEN CONVERT(VARCHAR(5), CONVERT(DATE, DateStr, 101), 101)
ELSE '00/00'
END AS [DD/MM]
FROM Dates

Related

Cast to datetime only if its a date value

I have a table with DateFrom column
it's an nvarchar col in the col I have data like that
01
02
10/10/2020
04
some strings and some DateTime values
I need to cast it to DateTime but only if it's a date if not then pull out the value like it is can is this possible?
thanks ...
a Simple Try cast should do the job here
DECLARE #Table TABLE (Val NVARCHAR(20))
INSERT INTO #Table
VALUES('1'),('2'),('10/10/2020'),('04')
SELECT
*,
TRY_CAST(Val AS DATE)
FROM #Table
Results
Something like this should work. It uses a CASE statement to check whether or not the value is a valid date and if so casts it to DATETIME, then converts it to VARCHAR (so dates and other values can be returned as the same column).
You can find other datetime to string styles here if you need them formatted differently:
https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver15
DECLARE #TempTable TABLE (Dt NVARCHAR(30))
INSERT INTO #TempTable
VALUES('1'),('2'),('10/10/2020'),('04'),('Jun 27 2021 12:22AM'),('Oct 12 2021 8:31PM')
SELECT
*,
CASE WHEN ISDATE(Dt) = 1 THEN Convert(VARCHAR, CAST(Dt AS DATETIME), 120) ELSE Dt END
FROM #TempTable
You can easily check this with the case statement.
Postgres example
select case when '12/12/2021' ~ '\d{2}\/\d{2}\/\d{4}' then 'this is the date' ELSE 'this is a string' end;
->this is the date
select case when 'some text' ~ '\d{2}\/\d{2}\/\d{4}' then 'this is the date' ELSE 'this is a string' end;
->this is a string
so you can use it like this
select case when fild_01 ~ '\d{2}\/\d{2}\/\d{4}' then TO_DATE(fild_01,'DD/MM/YYYY')::text ELSE fild_01 end from test_table;
as you can see, case construction can't generalize two different types of data, so I had to convert them to the same type of text
Use the TRY_CONVERT function, with style 107
SELECT TRY_CONVERT(datetime, 'Jun 27 2021 12:22AM', 107)
Result
2021-06-27 00:22:00.000
This returns a null if the value is not a date
You can choose according to your needs.
When you want to set default value:
SELECT IIF(ISDATE(Val) = 1 , Val,'YOUR_DEFAULT_VALUE')
Whent default value not matter (It will be NULL):
SELECT TRY_CAST(NULL AS DATE)

Converting Varchar to Date and date Comparison

I am converting two Date columns to find the most recent one
SELECT ISNULL(CONVERT(varchar(10),REPLACE('10-07-2015','/','-'), 103),'01-01-1900'),
ISNULL(CONVERT(varchar(10),REPLACE('10/7/2015','/','-'), 103),'01-01-1900'),
CASE
WHEN ISNULL(CONVERT(varchar,REPLACE('10-07-2015','/','-'), 103),'01-01-1900') = ISNULL(CONVERT(varchar,REPLACE('10/7/2015','/','-'), 103),'01-01-1900')
THEN '10-07-2015'
END
My issue is some dates missing leading Zero in Day or Month and comparison is giving false results. Is there a better way to handle this? Other issue is one column has date with '/' and other have with '-'
Currently case is only checking on '=' but will add more to get the most recent
You can just convert those 2 varchars to the DATE type, then compare them.
You can find the date/datetime styles here
For those DD/MM/YYYY datestamps the 103 style would fit.
And to calculate the most recent between them, just wrap it in a CASE.
Example snippet:
declare #T table (
id int identity(1,1) primary key,
datestamp1 varchar(10),
datestamp2 varchar(10)
);
insert into #T (datestamp1, datestamp2) values
('5/9/2018','17/9/2018')
,('9-10-2018','16-10-2018')
,('15-10-2018','13-10-2018')
;
SELECT *,
TRY_CONVERT(DATE, datestamp1, 103) as date1,
TRY_CONVERT(DATE, datestamp2, 103) as date2,
CASE
WHEN TRY_CONVERT(DATE, datestamp1, 103) >= TRY_CONVERT(DATE, datestamp2, 103) THEN datestamp1
WHEN TRY_CONVERT(DATE, datestamp2, 103) IS NULL THEN datestamp1
ELSE datestamp2
END AS MostRecentDatestamp
FROM #T;
Returns:
id datestamp1 datestamp2 date1 date2 MostRecentDatestamp
1 5/9/2018 17/9/2018 2018-09-05 2018-09-17 17/9/2018
2 9-10-2018 16-10-2018 2018-10-09 2018-10-16 16-10-2018
3 15-10-2018 13-10-2018 2018-10-15 2018-10-13 15-10-2018

Filter Data in SQL Server

I have a table like below :
[TMP_TBL]
(
...
[DT_REFUND] [varchar(20)] NULL,
[MSG_PROCESS] [nvarchar(max)] NULL,
...
)
and it contains data like this:
| DT_REFUND | MSG_PROCESS |
| A-BC---D | WRONG DATETYPE |
| 20180301 | NULL |
| 20180331 | NULL |
When I do a query like:
select *
from TMP_TBL
where isnull(MSG_PROCESS, '') = ''
everything goes fine.
But when I do query like:
select *
from TMP_TBL
where isnull(MSG_PROCESS, '') = ''
and convert(DATE, DT_REFUND) >= convert(DATE, '20180301');
I get an error:
Conversion failed when converting date and/or time from character string
Why did this happen, and how to fix it?
Thanks
Ideally you should have avoided using VARCHAR data type for dates.
For the current scenario, you can use TRY_CONVERT like following.
select *
from TMP_TBL
where isnull(MSG_PROCESS, '') = ''
and TRY_CONVERT(DATE, DT_REFUND) >= convert(DATE, '20180301');
As your date column is VARCHAR, so there is a possibility of having empty spaces also, to handle this you can try RTRIM function before converting to date like following.
TRY_CONVERT(DATE, RTRIM(DT_REFUND)) >= convert(DATE, '20180301');
First you check the value in the column is DATE format or other format, using ISDATE function. And compare with the date value.
If it is not in date format it returns NULL value.
Try this:
SELECT *
FROM TMP_TBL
WHERE ISNULL(MSG_PROCESS,'') = ''
AND CONVERT(DATE, CASE WHEN ISDATE(DT_REFUND)=1 THEN DT_REFUND ELSE NULL END) >= CONVERT(DATE, '20180301');
You just need to filter out null values and compared date via cast() or convert() function
select *
from TMP_TBL
where MSG_PROCESS is null and
cast(DT_REFUND as date) >= '20180301';
This assumes null value has always date as your sample data suggests
In other way, first you could check DT_REFUND has some kind of date format data via TRY_CONVERT() function. So, your where clause should do
where MSG_PROCESS is null and TRY_CONVERT(date, DT_REFUND) is not null and
cast(DT_REFUND as date) >= '20180301';
However, the above has some redundant filtration before cast so you could also express that as
where MSG_PROCESS is null and TRY_CONVERT(date, DT_REFUND) >= '20180301';

Issue in using TRY_PARSE in CASE WHEN Statement

I need to validate the dates with different formats like
Thursday March 15, 2018, 05-21-1995, 04.03.1934 and I may get Invalid Dates like N/A, #### etc.,. I am using the Following Query to validate the date in Stored procedure, here I insert the date into the date column and set Error Flag If there is an Invalid date.
INSERT INTO table_name(date_column,date_error)
SELECT
CASE WHEN TRY_PARSE(date_column AS datetime USING 'en-US') is NULL THEN date_column
ELSE TRY_PARSE(date_column AS datetime USING 'en-US')
END as date_column,
CASE WHEN TRY_PARSE(date_column AS datetime USING 'en-US') is NULL THEN 1
ELSE 0
END as date_error
FROM #temp_table;
I'm getting the Error as Conversion failed when converting date and/or time from character string for date value ####.
You cannot put two different types in one column
This may work for you
declare #T table (pk int identity primary key, varDt varchar(100));
insert into #T (varDt) values ('Thursday March 15, 2018'), ('05-21-1995'), ('N/A'), ('####'), ('easter'), ('');
declare #Tf table (pk int primary key, varDt varchar(100), needFix bit, dt datetime);
insert into #Tf
select t.pk, t.varDt
, case when TRY_PARSE(t.varDt AS datetime USING 'en-US') is null then 1 else 0 end as needFix
, TRY_PARSE(t.varDt AS datetime USING 'en-US') as dt
from #T t;
select *
from #Tf tf
order by needFix desc, pk;
Thanks for all your comments. As #gordon-linoff said we can't have two different datatypes in CASE WHEN Statement. So, I CAST the else statement to varchar.
INSERT INTO table_name(date_column,date_error)
SELECT
CASE WHEN TRY_PARSE(date_column AS datetime USING 'en-US') is NULL THEN date_column
ELSE CAST(TRY_PARSE(date_column AS datetime USING 'en-US') AS varchar(max))
END as date_column,
CASE WHEN TRY_PARSE(date_column AS datetime USING 'en-US') is NULL THEN 1
ELSE 0
END as date_error
FROM #temp_table;

TSQL Null data to '' replace

I have the following query:
SELECT pics.e_firedate FROM et_pics
Result:
NULL
2014-12-01 00:00:00.000
2015-04-03 00:00:00.000
NULL
NULL
I want to replace NULL values to ''.
CASE
WHEN pics.e_firedate IS NULL THEN ''
ELSE pics.e_firedate
END
makes NULL transforming to 1900-01-01 00:00:00.000, which I've tried to cast and replace with no success also.
How can I achive my goal?
That's because when using CASE expressions, the return values must have the same data type. In case they have different data types, all values are converted to the type with a higher data type precedence.
And since DATETIME has a higher datatype than VARCHAR, '' gets converted to DATETIME:
SELECT CAST('' AS DATETIME)
The above will return 1900-01-01 00:00:00.000.
To achieve your desired result, you should CAST the result to VARCHAR
SELECT
CASE
WHEN e_firedate IS NULL THEN ''
ELSE CONVERT(VARCHAR(23), e_firedate, 121)
END
FROM et_pics
For date formats, read this.
Try:
select isNUll(CONVERT(VARCHAR, pics.e_firedate, 120), '') e_firedate
FROM et_pics
SELECT
ISNULL(CONVERT(varchar(10),pics.e_firedate,120),'') e_firedate
FROM et_pics
You have to cast/convert datetime field, not other value - for example:
case
when pics.e_firedate is null
then ''
else cast(pics.e_firedate as nvarchar(30))
end
Well, the column in your database seems to be a DATETIME column. So SQL Server converts '' to the default date value.
One solution might be to convert all the results to string, as in:
SELECT ISNULL(CONVERT(NVARCHAR, pics.e_firedate), '') AS e_firedateString
FROM et_pics
Might be more efficient? And might not.
SELECT CONVERT(VARCHAR(23), e_firedate, 121) FROM et_pics where pics.e_firedate is not null
union
SELECT '' FROM et_pics where pics.e_firedate is null