SQL: extract date from string - sql

There is a text field called myDate. This field can contain either 1) 'Fiscal year ending someDate' or 2) 'dateA to 'dateB'.
In situation 1), I want to set the field date1 = to someDate.
In situation 2), I want to set the field date1 = dateA and the field date2 = dateB.
All the dates (someDate, dateA, dateB) can be written as 1/1/2000, Jan 1, 2000, or January 1, 2000.
How do I go about extracting the dates from myDate and inserting them into the correct fields?

This doesn't look complicated enough to need a "proper" regular expression. Those textual dates can be parsed directly into a DATETIME type by SQL without any mucking around, as you can see by running this query:
SELECT CAST('1/1/2000' AS DATETIME), CAST('January 1, 2000' AS DATETIME), CAST('Jan 1, 2000' AS DATETIME)
To get -1 year and +1 day, just use DATEADD, e.g.
SELECT DATEADD(dd, 1, DATEADD(yy, -1, 'January 1 2000'))
...so, all you really need to do is cope with your two different cases and grab the dates out. So, something like:
SELECT
CASE
WHEN myDate LIKE 'fiscal year ending %' THEN CAST(DATEADD(dd, 1, DATEADD(yy, -1, REPLACE(myDate, 'fiscal year ending ', ''))) AS DATETIME)
ELSE CAST(LEFT(myDate, PATINDEX('% to %', myDate)) AS DATETIME)
END 'FromDate',
CASE
WHEN myDate LIKE 'fiscal year ending %' THEN CAST(REPLACE(myDate, 'fiscal year ending ', '') AS DATETIME)
ELSE CAST(SUBSTRING(myDate, PATINDEX('% to %', myDate) + 4, 100) AS DATETIME)
END 'ToDate'
FROM
...whatever
...should do the trick. I've not really tested that, but hopefully it'll give you enough of an idea to see what I'm getting at.
Note that some of the results will probably depend on the language settings of your server/database. For example, while 1/1/2000 is always going to be 1 Jan, is 3/4/2000 the third of April, or the fourth of March?

Related

Date conversion for YY-Monthtext to MM/DD/YYYY

Receive date as "19-May" and need to convert it as '05/01/2019', "19-June" to '06/01/2019'.
I have tried various date conversion but it didn't work.
You can try this. Storing date in this format is not a good/suggestion you should use the proper data type which are meant and available for.
You should update the values with proper date time value and then change the data type also. It will save your time & you do not need these conversions every time.
Select Try_Cast('19-May 2019' as Datetime)
OR
Select Try_Cast('19-May' + '2019' as Datetime)
To get the first date of month you can try the below query.
SELECT DATEADD(month, DATEDIFF(month, 0, Try_Cast('19-May 2019' as Datetime)), 0) AS StartOfMonth
Edit
To get the first date of month as per the given data in string, you can use the below query.
declare #dateinStr varchar(20) = '19-May'
Select try_cast('01-' + Replace(#dateinStr, LEFT(#dateinStr, 3), '') + LEFT(#dateinStr, 2) as Datetime) as Date
Here is the demo.
I suppose the months will be 3 chars only, if so then
Select s,
try_Cast(concat(right(s, 3), ' 2019') as Datetime)
from
(
values
('19-May'),
('19-Jun')
) t(s);
If the months is really comes like "June" & "August" then
select s,
try_cast(concat(substring(s, charindex('-',s)+1, 3), ' 2019') as date)
from
(
values
('19-May'),
('19-June'),
('15-August')
) t(s);
If you need to format it as mm/dd/yyyy then use 101 style.
You can do :
SELECT DATEADD(DAY, 1, EOMONTH(CONVERT(DATE, Dates + '-2019'), -1))
FROM ( VALUES ('19-May'), ('19-June')
) t(Dates);

How to pull data from Starting month of year to the given month based on the month parameter value

IF I Select #rpmMonth = SEP 2019 it should pull the data from JAN 2019 to SEP 2019
**I Have only One Parameter Value i.e #rpmMonth of VARCHAR Type.
Declare #firstDay Date=(
select convert(varchar(10),DATEADD(Year,-1*DateDiff(Year,getdate(),0),0),120))
Declare #CurDate Date=(
SELECT convert(varchar(10),DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0)),120))
select * from YOURTABLE
where colname between #firstDay and #CurDate
Ideally, you should be using a date datatype, not a varchar. If we do, however, have to use a varchar then you could do something like this:
SELECT {Columns}
FROM {Your Schema And Table}
WHERE {DateColumn} >= CONVERT(date,CONCAT(RIGHT(#rpmMonth),'0101'))
AND {DateColumn} < DATEADD(MONTH, 1, CONVERT(date, '01 ' + #rpmMonth));
(Obviously replace the parts in braces ({}) and assumes the language of the LOGIN is an English based language.)
This would give you all rows on or after Jan 01 of the year for #rpmMonth and before the month after #rpmMonth.
If you use a proper date, and pass the first date of the month i.e. (2019-09-01 for the sample you gave), then you could do the below:
SELECT {Columns}
FROM {Your Schema And Table}
WHERE {DateColumn} >= DATEADD(YEAR, DATEDIFF(YEAR, 0, #rpmMonth),0)
AND {DateColumn} < DATEADD(MONTH, 1, #rpmMonth);
SQL Server is pretty good about converting date values. You should be able to do:
select . . .
from t cross join
(values (convert(date, #rpmMonth)) as v(dte)
where datecol >= datefromparts(year(v.dte), 1, 1) and
datecol < datefromparts(year(dateadd(month, 1, v.dte)), month(dateadd(month, 1, v.dte)), 1)

SQL Find/Ignore invalid date

I am using SQL Server.
From each row, I take day and month values from the fields c.daybirth,c.monthbirth
and the year from getdate(), and I want to have a field that shows if this date is valid or not (invalid example: 31 February)
I have created this solution:
case day(dateadd(month,c.monthbirth-1,dateadd(day,c.daybirth-1,DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0)))) when c.daybirth then 1 else 0 end
which works, but I find it hard to read. Is there a smarter alternative?
In SQL Server 2012+, you can do:
where try_convert(date,
datefromparts(year(getdate()), c.monthbirth, c.daybirth)
) is not null
EDIT:
Amusing. This is better:
where try_convert(date,
cast(year(getdate()) * 10000 + c.monthbirth * 100 + c.daybirth as varchar(255))
) is not null

Creating a dynamic date range in SQL

How can I construct a SQL statement that will always return a start date of July 1 of the previous year, and an end date of June 30 of the current year based on GETDATE()? Right now I have
Dateadd(yy, Datediff(yy,1,GETDATE())-1,0) AS StartDate,
DateAdd(dd,-1,Dateadd(yy, Datediff(yy,0,GETDATE()),0)) AS EndDate
which will return January 1, 2012 and December 31, 2013 respectively..
You could just add another DATEADD() to your current script:
SELECT DATEADD(month,6,DATEADD(yy, DATEDIFF(yy,1,GETDATE())-1,0)) AS StartDate
,DATEADD(month,6,DATEADD(dd,-1,DATEADD(yy, DATEDIFF(yy,0,GETDATE()),0))) AS EndDate
This seems like an odd request. One way of doing it is by constructing date strings and parsing them:
select cast(cast(year(GETDATE()) - 1 as varchar(255))+'-07-01' as DATE) as StartDate,
cast(cast(year(GETDATE()) as varchar(255))+'-06-30' as DATE) as EndDate
This constructs the strings in the format '2013-06-30', which will be interpreted correctly on for most SQL Server date settings.
I believe (recalling something Aaron Bertrand wrote) that leaving out the hyphens always works:
select cast(cast(year(GETDATE()) - 1 as varchar(255))+'0701' as DATE) as StartDate,
cast(cast(year(GETDATE()) as varchar(255))+'0630' as DATE) as EndDate
I, as a human, just much prefer having the hyphens.
I've been using this CTE for dynamic fiscal year ranges based on the current date. It returns the start and end dates for the current fiscal year based on the current date.
WITH FYDates AS (
SELECT
CASE
WHEN MONTH(GETDATE()) IN (1, 2, 3, 4, 5, 6)
THEN CAST(CAST(YEAR(GETDATE()) - 1 AS VARCHAR) + '/07/01' AS DATE)
ELSE CAST(CAST(YEAR(GETDATE()) AS VARCHAR) + '/07/01' AS DATE) END AS FYStartDate,
CASE
WHEN MONTH(GETDATE()) IN (1, 2, 3, 4, 5, 6)
THEN CAST(CAST(YEAR(GETDATE()) AS VARCHAR) + '/06/30' AS DATE)
ELSE CAST(CAST(YEAR(GETDATE()) + 1 AS VARCHAR) + '/06/30' AS DATE) END AS FYEndDate
),
You can also create this as a view to reference that when needed.
This should work for you:
SELECT CAST('7/1/' + CAST(DATEPART(yy, Dateadd(yy, Datediff(yy,1,GETDATE())-1,0)) as varchar) as varchar) as startdate,
CAST('6/30/' + CAST(DATEPART(yy, Dateadd(yy, Datediff(yy,0,GETDATE()),0)) as varchar) as varchar) as enddate

SQL replace date values if date is Saturday or Sunday

(Sorry, I couldn't think of a better title)
I have created the following select statement (SQL Server) to work as a view.
SELECT DISTINCT
dbo.ECB.Currency + '-' +
CAST(dbo.ECB.Date AS varchar(30)) AS ComboDate,
dbo.ECB.Rate AS ECBrate
FROM
dbo.ECB
INNER JOIN
dbo.MyTable ON dbo.ECB.Date = dbo.MyTable.CutoffDate
AND dbo.ECB.Currency = dbo.MyTable.MyCurrency
My problem:
What I've noticed is that I have Saturday and Sunday dates in my CutoffDate column but not in the ECB date column - meaning I have no rates for those days.
Since I use the CutoffDate in Excel calculations I would like the view to "replace" the date values for Saturday and Sunday with Friday.
I found this working snippet and modified it to my needs.
SELECT
DISTINCT
CASE WHEN DATEPART(weekday, dbo.CutoffDate) IN (6, 7)
THEN DATEADD(d, -((DATEPART(weekday, dbo.CutoffDate) + 1 + ##DATEFIRST) % 7), dbo.CutoffDate)
ELSE dbo.CutoffDate
END
FROM
MyTable
Now I need to find a way to combine both structures and this is where I'm hoping that you can help me out with.
I wanted to add the second select statement to my view but failed in doing so.
thank you.
If you move your case statement into the join, it should work.
Change
dbo.MyTable ON dbo.ECB.Date = dbo.MyTable.CutoffDate
To
dbo.Mytable ON dbo.ECB.Date = case when datepart(weekday, dbo.CutoffDate) IN (6,7)
then dateadd(d, -((datepart(weekday, dbo.CutoffDate) + 1 + ##DATEFIRST) % 7), dbo.CutoffDate)
else dbo.CutoffDate
end
Hope this helps.