SQL Server the closest 1st February - sql

Could you please help in finding the closest February 1st to current date?
The following script works correctly only if it is ran in current year:
select DATEADD(MONTH,1,DATEADD(year, DATEDIFF(year, -1, GETDATE()), 0))
But when it would be ran in January next year it will produce incorrect result.
Thank you in advance!

Your question can be interpreted two different ways: the first being to find the next closest Feb 1 (i.e. Feb 2 2016 will return Feb 1 2017), and the second being to find the closest Feb 1 to the current date (i.e. Feb 2 2016 will return Feb 1 2016).
Prdp has already supplied an answer for the former, so this approach (which I'm sure can be simplified) will be for the latter.
This will consider the current year's Feb 1 and the next year's Feb 1, and compute the DateDiff() in days from both, and select the closest one.
;With Dates As
(
Select ThisFeb = DateFromParts(Year(GetDate()), 2, 1),
NextFeb = DateFromParts(Year(GetDate()) + 1, 2, 1)
), Distance (Date, Distance) As
(
Select ThisFeb, Abs(DateDiff(Day, GetDate(), ThisFeb)) As ThisFebDiff
From Dates
Union All
Select NextFeb, Abs(DateDiff(Day, GetDate(), NextFeb)) As NextFebDiff
From Dates
)
Select Top 1 Date
From Distance
Order By Distance Asc

Try something like this using IIF and DATEFROMPARTS
select IIF(month(getdate()) > 2,
DATEFROMPARTS(YEAR(Getdate()),2,1),DATEFROMPARTS(YEAR(Getdate())-1,2,1) )
If you are using older versions then
select Case When month(getdate()) > 2
then CAST(CAST(YEAR(getdate()) as char(4))+'-02-01' as date)
else CAST(CAST(YEAR(getdate()) - 1 as char(4))+'-02-01' as date)
end

Try This:
SELECT
CASE WHEN
DATEDIFF(dd,CAST(CONCAT(year(GETDATE()),'-02-01') AS DATE),GETDATE()) < 183
THEN CAST(CONCAT(year(GETDATE()),'-02-01') AS DATE)
ELSE CAST(CONCAT(year(GETDATE())+1,'-02-01') AS DATE) END as ClosestFebFirst

This is another possible solution...
DECLARE #SomeDate DATE = '2017-06-30';
SELECT TOP 1
ClosestFebFirst = CASE WHEN dd.Diff1 < dd.Diff2 THEN pd.D1 ELSE pd.D2 END
FROM
( VALUES (
DATEFROMPARTS(YEAR(#SomeDate), 2, 1),
DATEFROMPARTS(YEAR(#SomeDate) + 1, 2, 1)
)
) pd (D1, D2)
CROSS APPLY ( VALUES (
ABS(DATEDIFF(dd, #SomeDate, pd.D1)),
ABS(DATEDIFF(dd, #SomeDate, pd.D2))
)
) dd (Diff1, Diff2);

Related

SQL query to find dates of last year equivalent to today's date

I am writing a SQL query to find business working dates of last year equivalent to today's date.
In this query it should fetch :-
For e.g. if today is 5th January, 2021 and it is the second day of second week of the year. So I need to find the exact equivalent date of the second day of second week of the previous year. So it would be 7th January, 2020.
And with this, I need the business working dates of that week of 7th January 2020 (i.e. excluding Saturday & Sunday)
Which will come up as 2020-Jan-06 to 2020-Jan-10 according to the example.
So I will need the report between 6th Jan - 10th Jan, 2020.
I am trying to use this code to find date of last year equivalent to today's date (5th Jan, 2021 viz. second day of second week)
select Convert(date, (DATEADD(year, -1, getdate()+2))) ;
2021-01-05 is the 2nd day of the first week of 2021 according to ISO standards.
If you want the 2nd day of the first week of 2021, then it is either today's date minus 52 weeks or 53 weeks. Based on the Wikipedia page for ISO dates:
[53 week years are those] years in which 1 January or 31 December are Thursdays
So, we want that for the previous year. Hence, I think the following should work:
select dateadd(week,
(case when 'Thursday' in (datename(weekday, datefromparts(year(getdate()) - 1, 1, 1)),
datename(weekday, datefromparts(year(getdate()) - 1, 12, 31))
)
then -53 else -52
end),
convert(date, getdate())
)
Note that this returns 2019-12-31, which is the correct value based on ISO standards.
I have use multiple CTE to show you the step by step calculation. It should be pretty easy to follow.
Basically it find the week_no and day_no_of_week for 2021-01-05 and then use that to find the same date for 2020
declare #input_date date = '2021-01-05',
#year_offset int = -1; -- previous year
with
cte1 as
(
select input_date = #input_date,
week_no = DATEPART(WEEK, #input_date),
first_day_of_week = DATEADD(WEEK, DATEDIFF(WEEK, 0, #input_date), 0)
),
cte2 as
(
select *,
day_no_of_week = DATEDIFF(DAY, first_day_of_week, #input_date) + 1
from cte1
),
cte3 as
(
select *,
first_day_of_the_prev_year = DATEADD(YEAR, DATEDIFF(YEAR, 0, #input_date) + #year_offset, 0)
from cte2
),
cte4 as
(
select *,
first_day_of_week_prev_year = DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(WEEK, week_no - 1, first_day_of_the_prev_year)), 0)
from cte3
)
select *,
DATEADD(DAY, day_no_of_week - 1, first_day_of_week_prev_year) as the_required_date
from cte4

Create date column from 3 strings in SQL

I have a table with 3 columns:
(integer) (integer) (varchar(50))
Month Year Color
1 2019 Blue
1 2019 Yellow
1 2019 Red
2 2019 Blue
2 2019 White
My end goal is to be able to make a query like this:
Select Color from table where (cast(concat(Year,'/',Month,'/1') as date)>='01/Jan/2019' and cast(concat(Year,'/',Month,'/1') as date)<'1/Mar/2019')
What i want is to be able to create a date from the columns i have in order to do a query within a range of dates.
I tried making the date with this query but it gives me this error:
Select cast(concat(Year,'/',Month,'/1') as date) from table
Conversion failed when converting date and/or time from character string.
Solution:
This is the final query that i used to get the dates in a Fiscal Year from Oct-2017 to Sep-2018.
select distinct(DATEFROMPARTS(y,m,1))
from table
where
(DATEFROMPARTS(y, m, 1) >= cast('2017-10-01' as date)) and (DATEFROMPARTS(y, m, 1) < cast('2018-10-01' as date))
order by DATEFROMPARTS(y,m,1)
Edit
Edited to switch cast to datefromparts
select distinct(DATEFROMPARTS(y,m,1))
from table
where
(DATEFROMPARTS(y, m, 1) >= DATEFROMPARTS(2017, 10, 1)) and (DATEFROMPARTS(y,m, 1) < DATEFROMPARTS(2018, 10, 1))
order by DATEFROMPARTS(y,m,1)
You can use datefromparts():
select color
from table
where
datefromparts(year, month, 1) >= cast('20190101' as date)
and datefromparts(year, month, 1) < cast('20190301' as date)
Or:
where
datefromparts(year, month, 1) >= datefromparts(2019, 1, 1)
and datefromparts(year, month, 1) < datefromparts(2019, 3, 1)
Since you are forcing the date to the first date of the month, you could also use between like so:
select color
from table
where datefromparts(year, month, 1)
between cast('20190101' as date) and cast('20190201' as date)
Or:
where datefromparts(year, month, 1)
between datefromparts(2019, 1, 1) and datefromparts(2019, 2, 1)
Note that for this date range, you could as well do simple number comparison:
where year = 2019 and month in (1, 2)
However if your date range spans over multiple years, this will get tedious and require a more complex expression.

last date of Financial year (I.e 2017-03-31)

Hi please let me know how to extract the last day of Financial year in sql server.my financial year start from 2016-04-01 to 2017-03-31
Closest you can use is End Of Month for that you need to provide one date to that month as below:
select eomonth('2017-03-01')
To get the last day of the financial year for any date, you need to find the last of march if before march, or the last of march next year if after march:
declare #yourdate datetime = getdate();
select case when month(#yourdate) < 4 then CONVERT(datetime,cast(YEAR(#yourdate) as char(4)) + '-03-31' ,120)
else CONVERT(datetime,cast(YEAR(#yourdate) + 1 as char(4)) + '-03-31' ,120)
end as financial_year_end
Edit:
If you want last date derived based on from_date, then use something like this
Rextester Demo
select
case when datepart(mm,from_date) <=3 then
cast(concat(year(from_date),'-03-31') as datetime)
else
dateadd(year,1,cast(concat(year(from_date),'-03-31') as datetime))
end as last_date_fin
from
(select '2017-04-30' as from_date union all
select '2017-01-13') t;
This way from_date between Jan - Mar will give same year's 31st march. Else it will give next year's 31st March.
Previous answer:
http://rextester.com/AXVM26769
If you want to get last day of march for same year as passed, then use
select cast(concat(given_year,'-03-31') as datetime)
from
(select '2017' as given_year) t
If you want to pass 2016 and then get 2017-03-31 then use. You can change the year in derived table and change the output based on that.
select dateadd(year,1,cast(concat(given_year,'-03-31') as datetime))
from
(select '2016' as given_year) t;
This Code will work to find the last date of Financial Year.
For Previous Year case matches and 'THEN' part will Execute and for current year 'ELSE'
part will execute.
select CASE WHEN (MONTH(GETDATE())) <= 3
THEN convert(varchar(4), YEAR(GETDATE())-1) + '-' + '03-31'
ELSE convert(varchar(4),YEAR(GETDATE()))+ '-' + '03-31'
end
> LastDayOfYearFY] =
> eomonth( dateadd(month, 5,
> dateadd(year, datepart(year, (dateadd(month, 6, [date])) ) -1900, 0)))
Idea extension taken from return-first-day-of-financial-year
You can select all the dates order them descendant and take the first one.
SELECT date
FROM table
ORDER BY date desc
LIMIT 1;

How to get week number SQL Server 2014

How to get Week number based on current date in SQL Server 2014?
Please note always year should starts from 1st February and year end will be 31st Jan.
Week Starts from Sunday to Saturday.
You can get the number of weeks since Feb 1 and then use that to calculate weeks:
select (case when month(getdate()) < 2
then datediff(week,
datefromparts(year(getdate()) - 1, 2, 1),
getdate()
)
else datediff(week,
datefromparts(year(getdate()), 2, 1),
getdate()
)
end)
Note: datefromparts() was introduced in SQL Server 2012. You can do similar things with strings and conversion to dates.
Try this
SELECT CASE WHEN MONTH(GETDATE()) < 2 THEN (DATEPART(DAYOFYEAR,DATEADD(M,11,GETDATE())))/7
ELSE ((DATEPART(DAYOFYEAR,GETDATE())-31)/7)+1
END
declare #DATE_INSERT date='02-01-2014'
select DATEPART(WK,#DATE_INSERT) - DATEPART(WK,DATEADD(DAY,1,DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#DATE_INSERT),0)))) + 1
Depends how you define week number, but you can try this:
SELECT DATEPART( wk, DATEADD('mm',-1,getdate()))

How to insert weekdays names in sql column based on given date?

I wanted to know how to insert weekday names in a column in sql server based on the current date. I want to insert the days until current day. For example, I want something as per the following column for today (2014-12-04),
day_of_week
-----------
Monday
Tuesday
Wednesday
Thursday
On next Tuesday(2014-12-09), I want to display,
day_of_week
-----------
Monday
Tuesday
Let me know how can I do this in sql server 2012?
Any help will be appreciated.
Thanks.
Something like this should work.
select datename(weekday,n)
from (VALUES (0),(1),(2),(3),(4),(5),(6)) wdays(n)
where n < datepart(weekday,'20141209') - 1
And if you're not using sql 2008 and up you can do
select datename(weekday,n)
from (select 0
union all
select 1
union all
select 2
union all
select 3
union all
select 4
union all
select 5
union all
select 6
) wdays(n)
where n < datepart(weekday,'20141209') - 1
It can also be done using a recursive CTE:
;WITH cte AS
(
SELECT DATENAME(weekday,getdate()) AS NameOfDay,
DAY(getdate()) AS NumberOfDay,
getdate() AS curDate
UNION ALL
SELECT DATENAME(weekday,DATEADD(day, -1, curDate)) As NameOfDay,
DAY(DATEADD(day, -1, curDate)) AS NumberOfDay,
DATEADD(day, -1, curDate) AS curDate
FROM cte
WHERE DAY(GETDATE()) - DAY(DATEADD(day, -1, curDate)) >= 0
)
SELECT NameOfDay
FROM cte
ORDER BY NumberOfDay