sql code to get week number for FiscalYear - sql-server

Need sql code to get week number for FiscalYear –
Date table ranges from 1975 to 2024
Already have weekno (WeekOfYear) for CalendarYear
-week count start from 1st of April and end on 31st march
-Week start from Sunday to Saturday
-On Fiscalyear end, week also ended
eg.
1st apr 2016 -Week 1
2nd apr 2016 - week 1
3rd apr 2016 to 9th apr 2016 -week 2
10th apr 2016 to 16th apr 2016 -week 3 ... and so on

assuming DATEFIRST is 7, I got this function - actually you can default datefirst = 7 for the lifetime of your query only - this seems to work according to by 1980 calendar
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date, ,>
-- Description: <Description, ,>
-- =============================================
CREATE FUNCTION FiscalYearMonth
(
#DAT datetime
)
RETURNS int
AS
BEGIN
DECLARE #TAXY as int;
DECLARE #R as int;
SET #TAXY = YEAR(dateadd(month,-3,#dat));
DECLARE #TDAT as varchar(8)
SET #TDAT = CAST(#TAXY AS varchar(4)) + '0401';
SELECT #R = datediff(day, DATEADD(day , (8 - DATEPART(DW,#TDAT)) % 7,#TDAT), dateadd(day,14,#DAT)) / 7;
RETURN #R;
END
GO
e.g.
SET datefirst 7;
select dbo.FiscalYearMonth('19800413')

Writing a query to do this, seems to me very complicated. I advise you to do it either by using a table (Choice1) or by creating an EXCEL file (Choice2).
Choice1: Create a WeekCalendarForFiscalYear table with 4 fields [DateOfToday, weekNumber, FiscalYear].
In DateOfToday, you put the date of the day.
In WeekNumber, you put the number of the fiscal week.
In FiscalYear, you are in the fiscal year (2016, 2017, 2018, etc.).
You have to think about indexing these fields.
/!\ : You can also create your table like this: WeekCalendarForFiscalYear with 4 fields [WeekNumber, FiscalYear, StartDate, EndDate]. StartDate would correspond to the beginning of the fiscal week and EndDate at the end of the fiscal week.
Choix2: You create an EXCEL file in which you enter the data either as in Choix1, or as it suits you.
The file must be physically on the server of the database.
You access the file via OPENROWSET. You will find on the web a wide
range of sites that will help you to use OPENROWSET well.
Hope this can help.

Related

Get current school year from the current date in SQL Server

So there is a very similar forum post to this one but I cannot run those commands. I am using SQL Server 2008 R2 and need help getting the current school year.
Basically I need a way to generate the current school year by using the current date. From Aug. of the current year until Aug. of the next year it will be 1 school year.
Ex. Aug. 2015 - July 2016 will need to pull up the year 2015 and Starting Aug. 2016 the year 2016 will need to pull up.
I am still fairly new to SQL so any help would be greatly appreciated.
Sounds like you're looking for this:
IF Month(GetDate()) >=8
BEGIN
SELECT Year(GetDate())
END
ELSE
BEGIN
SELECT Year(GetDate())-1
END
EDIT:
To use this in a select statement's where clause:
DECLARE #currentSchoolYear INT
IF Month(GetDate()) >=8
BEGIN
SELECT #currentSchoolYear = Year(GetDate())
END
ELSE
BEGIN
SELECT #currentSchoolYear = Year(GetDate())-1
END
SELECT * FROM dbo.dates
WHERE CASE WHEN Month(datevalue) >=8 THEN Year(datevalue)
ELSE Year(datevalue)-1
END = #currentSchoolYear
obviously replace "dbo.dates" with your table name, and "datevalue" with whatevercolumn you're comparing. This will return the rows from the current school year
SELECT value1, value,
(CASE WHEN GETDATE() BETWEEN '20150801' AND '20160731' THEN 2015
WHEN GETDATE() BETWEEN '20160801' AND '20170731' THEN 2016
ELSE 2014) AS schoolYear
FROM dbTable
WHERE ...

SQL Week of Month without DATEFIRST

I am working with dates so I have created a function that generates a SQL Table Calendar which returns Day, Month, WeekOfMonth, WeekOfYear and so on.
Right now, for the Day of Month field I am using the following function:
-- [WkNo]=Week number
[WkNo] = DATEPART(week,dt.DT),
But the problem is that when I run this on a SQL installed with Language = US English, the week setting is wrong cause the week starts from Sunday.
I need to set the week starting from Monday, is it possible without the use of DATEPART?
Update: based on asker's comment that he cannot use the DATEFIRST approach I am updating answer.
Note:
This answer is generic in nature.
If instead of Monday you want the week to start from Tuesday, you can change the dateadd(dd,-1,dt.DT) to dateadd(dd,-2,dt.DT) and for Wednesday to dateadd(dd,-3,dt.DT).
Basically the formula becomes dateadd(dd,-n,dt.DT) for value of n ranging over 1(Monday) to 6 (Saturday).
SELECT [WkNo]=
ISNULL(DATEPART(week,
case
when Year(dt.DT)>YEAR(dateadd(dd,-1,dt.DT))
then null
else dateadd(dd,-1,dt.DT)
end
),1)
See working fiddle http://sqlfiddle.com/#!6/10a80/14
Old Answer:
See MSDN documentation: https://msdn.microsoft.com/en-us/library/ms174420.aspx
When datepart is week (wk, ww) or weekday (dw), the return value
depends on the value that is set by using SET DATEFIRST. January 1 of
any year defines the starting number for the week datepart, for
example: DATEPART (wk, 'Jan 1, xxxx') = 1, where xxxx is any year.
SET DATEFIRST 1
-- [WkNo]=Week number
[WkNo] = DATEPART(week,dt.DT),
try
SET DATEFIRST {1,2,3,4,5,6,7(default, U.S. English)}
for your Query:
set datefirst 1
select [WkNo]= DATEPART(week,dt.DT)
See Here

SQL Server date calculations in stored procedures

I wanted to ask 3 questions about below code (please excuse the long code listing, I am including these lines in the hopes that it provides enough context).
Note that the code here depends on the date when it is executed. For this reason my questions refer to a hypothetical situation with two different execution dates:
March 1st 2014
January 1st 2014
My questions are on whether my understanding on some parts of this is correct, i.e:
A. that the SELECT DATEADD expression (on line 1) would:
On March 1st 2014 create the datetime 2014-02-31 23:59:59
B. that the code on lines 6-9 would:
On March 1st 2014 create the datetime 2014-02-01 00:00:00
On January 1st 2014 create the datetime 2013-02-01 00:00:00
and
C. that the code on lines 11-14 would:
On March 1st 2014 create the datetime 2015-01-30 00:00:00
On January 1st 2014 create the datetime 2014-01-30 00:00:00
Is this understanding correct?
1. SET #ldpmth = (SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0)) )
2. SET #yr = (SELECT YEAR(#ldpmth))
3. SET #mth = 0
4. SET #dy = 0
5.
6. SET #fysdate = (SELECT CASE WHEN MONTH(#ldpmth) >= 2 THEN
7. DATEADD(MM, 1,CAST(CAST(#yr+#mth+#dy AS NVARCHAR(50)) AS DATETIME))
8. ELSE DATEADD(MM, 1, CAST(CAST((#yr-1)+#mth+#dy AS NVARCHAR(50))
9. AS DATETIME)) END )
10.
11. SET #fyedate = (SELECT CASE WHEN MONTH(#ldpmth) >= 2 THEN
12. DATEADD(YY, 1, CAST(CAST(#yr+#mth+#dy AS NVARCHAR(50)) AS DATETIME)) + 30
13. ELSE DATEADD(YY, 1, CAST(CAST((#yr-1)+#mth+#dy AS NVARCHAR(50))
14. AS DATETIME)) + 30 END )
(Thank you for all who answered so far. This is actually code that was developed (but not documented) at my place of employment some years ago and I have been tasked with converting it to a form that works client-side with Crystal Reports.)
On March 1st 2014 create the datetime 2014-02-31 23:59:59
No. AFAIK, there isn't any dbms that's so dumb it thinks Feb 31 is an actual date. The SQL statement on line 1 will return the value 'Feb 28 2014 23:59:59'.
You can test all your statements by substituting actual dates for GETDATE() and guesswork. In the first query, for example, use
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,'2014-03-01'),0));
^^^^^^^^^^
You can probably run a version of SQL Server locally. SQL Server 2008 even installs on Windows XP. If you can't bear that, though, there's always sqlfiddle.com.
This could be easily tested in SQL Server Management Studio (SSMS). I'll answer the first, and you can test the next two yourself.
Question:
A. that the DATEADD (on line 1) would on March 1st 2014 create the datetime 2014-02-31 23:59:59
Answer: No, because February can't possibly have 31 days, so it can't return '2014-02-31`
Proof:
select DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,'2014-03-01'),0))
Results
(No column name)
2014-02-28 23:59:59.000
For (B) and (C), if you'd stated your question, instead, as "My financial years run from 1st February until 30th(sic) January - how do I get the start and end dates for the current financial year, I'd have offered:
SET #fysdate = DATEADD(year,DATEDIFF(month,'19000201',GETDATE())/12,'19000201')
and:
SET #fyedate = DATEADD(year,DATEDIFF(month,'19000201',GETDATE())/12,'19010131')
(Note that this second finds the 31st Jan, not the 30th. I assume that was carelessness in your original question).
But, as to (A), as I indicated, I thought your question is again poorly phrased - if you're trying to find the end point of a period and that period is defined on datetimes (as opposed to just dates), it's far easier to construct an exclusive upper bound:
SET #ldpmth = DATEADD(month, DATEDIFF(month,0,GETDATE()),0)
This bound (to be used with a < comparison rather than <= or BETWEEN) doesn't artificially exclude any values with a time such as 23:59:59.527. Note also, that if the financial year end date calculation is going to be used against datetime values which include times, I'd again counsel computing an exclusive upper bound, and substitute 19010201 instead of 19010131.
So, in total, I don't think I've actually answered your questions as posed, but I think I've provided the answers you should have been seeking.

Generate datetime range SQL Server 2000

I am trying to generate dates for the whole year of 2012 in datetime format to store in a SQL Server table in a datetime column.
How is that done?
So start date would be 1/1/2012 until 31/12/2012 but in the correct format. I am assuming I should have 365 rows generated. Any idea?
CREATE TABLE DateTimeRange2012([Date] DATETIME NOT NULL)
GO
INSERT INTO DateTimeRange2012([Date])
SELECT DATEADD(day, Number, '20120101')
FROM master..spt_values
WHERE Number < 366 AND type = 'P'
Much more clear for keeping the values persisted?
Nice answer from Oleg Dok.
To expand upon his answer, here's a stored procedure that accepts a year and generates all of the dates for the year. This takes into account leap years.
CREATE PROCEDURE GenerateDates (#Year INT)
AS
SET NOCOUNT ON
DECLARE #FirstDate DATETIME
DECLARE #NoOfDates INT
SET #FirstDate = DateAdd(Year, #Year-1900, 0)
IF MONTH(DATEADD(Day, 59, #FirstDate))=3
SET #NoOfDates = 365
ELSE
SET #NoOfDates = 366
INSERT INTO DateTimeRange([Date])
SELECT DATEADD(day, Number, #FirstDate)
FROM master..spt_values
WHERE Number < #NoOfDates AND type = 'P'
One proviso. I believe that "spt_values" may not be supported and may be removed in future versions of SQL Server. However, I have read that it is being used in SQL Server 11 example code so perhaps it's not a worry just yet.

Getting week number off a date in MS SQL Server 2005?

Is it possible to create an sql statement that selects the week number (NOT the day of week - or the day number in a week). I'm creating a view to select this extra information along with a couple of other fields and thus can not use a stored procedure. I'm aware that it's possible to create a UDF to do the trick, but if at all possible i'd rather only have to add a view to this database, than both a view and a function.
Any ideas? Also where i come from, the week starts monday and week 1 is the first week of the year with atleast 4 days.
Related:
How do I calculate the week number given a date?
Be aware that there are differences in what is regarded the correct week number, depending on the culture. Week numbers depend on a couple of assumptions that differ from country to country, see Wikipedia article on the matter. There is an ISO standard (ISO 8601) that applies to week numbers.
The SQL server integrated DATEPART() function does not necessarily do The Right Thing. SQL Server assumes day 1 of week 1 would be January 1, for many applications that's wrong.
Calculating week numbers correctly is non-trivial, and different implementations can be found on the web. For example, there's an UDF that calculates the ISO week numbers from 1930-2030, being one among many others. You'll have to check what works for you.
This one is from Books Online (though you probably want to use the one from Jonas Lincoln's answer, the BOL version seems to be incorrect):
CREATE FUNCTION ISOweek (#DATE DATETIME)
RETURNS INT
AS
BEGIN
DECLARE #ISOweek INT
SET #ISOweek = DATEPART(wk,#DATE)
+1
-DATEPART(wk,CAST(DATEPART(yy,#DATE) AS CHAR(4))+'0104')
-- Special cases: Jan 1-3 may belong to the previous year
IF (#ISOweek=0)
SET #ISOweek = dbo.ISOweek(CAST(DATEPART(yy,#DATE) - 1
AS CHAR(4))+'12'+ CAST(24+DATEPART(DAY,#DATE) AS CHAR(2)))+1
-- Special case: Dec 29-31 may belong to the next year
IF ((DATEPART(mm,#DATE)=12) AND
((DATEPART(dd,#DATE)-DATEPART(dw,#DATE))>= 28))
SET #ISOweek=1
RETURN(#ISOweek)
END
GO
You need the ISO week. From http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=60510, here's an implementation:
drop function dbo.F_ISO_WEEK_OF_YEAR
go
create function dbo.F_ISO_WEEK_OF_YEAR
(
#Date datetime
)
returns int
as
/*
Function F_ISO_WEEK_OF_YEAR returns the
ISO 8601 week of the year for the date passed.
*/
begin
declare #WeekOfYear int
select
-- Compute week of year as (days since start of year/7)+1
-- Division by 7 gives whole weeks since start of year.
-- Adding 1 starts week number at 1, instead of zero.
#WeekOfYear =
(datediff(dd,
-- Case finds start of year
case
when NextYrStart <= #date
then NextYrStart
when CurrYrStart <= #date
then CurrYrStart
else PriorYrStart
end,#date)/7)+1
from
(
select
-- First day of first week of prior year
PriorYrStart =
dateadd(dd,(datediff(dd,-53690,dateadd(yy,-1,aa.Jan4))/7)*7,-53690),
-- First day of first week of current year
CurrYrStart =
dateadd(dd,(datediff(dd,-53690,aa.Jan4)/7)*7,-53690),
-- First day of first week of next year
NextYrStart =
dateadd(dd,(datediff(dd,-53690,dateadd(yy,1,aa.Jan4))/7)*7,-53690)
from
(
select
--Find Jan 4 for the year of the input date
Jan4 =
dateadd(dd,3,dateadd(yy,datediff(yy,0,#date),0))
) aa
) a
return #WeekOfYear
end
go
Looks like the DATEPART mssql function should help you out with ...
DATEPART(wk, ‘Jan 1, xxxx’) = 1
Well I'll be.. turns out there is a way to set the first day of the week, DATEFIRST
SET DATEFIRST 1 -- for monday
Update: Now I understand better, what the OP wants.. which is custom-logic for this. I don't think MSSQL would have functions with such rich level of customization. But I may be wrong... I think you'll have to roll your own UDF here...sorry
FORGET THE OTHER ANSWERS
The question specifies "the week starts monday and week 1 is the first week of the year with atleast 4 days." This is ISO 8601 standard and what this answer provides. This function is used in production on our site.
This is all you need:
CREATE FUNCTION ISOweek (#DATE DATETIME)
RETURNS INT
AS
BEGIN
RETURN (datepart(DY, datediff(d, 0, #DATE) / 7 * 7 + 3)+6) / 7
END
GO
This will return you the week number of date entered in quotes
SELECT DATEPART( wk, 'enter the date over here' )
Looks like datepart will get you part of the way there, but you'll have to adjust to get your correct week number, based on the day of week of Jan 1 of the given year. I'm not familiar enough with T-SQL to do that, but it should be possible. Pity there isn't a mode argument as in MySQL
have you considered using the WEEK function?
This will get you the week of the year for the specified date that you pass in.
SELECT { fn WEEK(GETDATE()) } AS WeekNumber, { fn WEEK(CONVERT(DATETIME, '2008-01-01 00:00:00', 102)) } AS FirstWeekOfYear, { fn WEEK(CONVERT(DATETIME, '2008-12-31 00:00:00', 102)) } AS LastWeekOfYear
This outputs the following SQL2000 and SQL2005:
WeekNumber: 50
FirstWeekOfYear: 1
LastWeekOfYear: 53
I Hope this helps :)
Why yet again, people make mountains out of mole-hills, it astounds me?
So simple...
select DATEPART(wk, GETDATE())

Resources