SQL Week of Month without DATEFIRST - sql-server

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

Related

Why SQL datepart(ww,GETDATE()) returns current week + 1

I am trying to get current week of the calendar. Let's assume today is 2022-03-14 12:00:00.
I am using these 2:
select GETDATE() // returns 2022-03-14 12:00:00
select datepart(ww,GETDATE() //returns 12
But as per calendar 2022-03-14 12:00:00 should be 11st week.
From where is the difference coming from and how I can get basically current week?
GetDatePart(ww, ...) in SQL server is dependent on the set datefirst as documented here.
You can use GetDatePart(isoww, getdate()) instead to get ISO Week Number.

SQL Server: Making Monday the start of week

I have an issue (and as reading, it's not just me) with SQL server settings for Sunday as first day of week. But my company needs the weeks to cover the period Monday-Sunday. I tried SET DATEFIRST 1, but it doesn't affect the results. A simple example: today is Sunday; when I enter the following code in SQL, it results in week 33, but it should show week 32, and week 33 should start from tomorrow:
SET DATEFIRST 1
Select DatePart(week, getdate());
I changed the language in my login settings to British English, bit it didn't work, as well. Is there some other way to change the settings?
In most of my queries I need to show the results for last week, with a similar where clause:
WHERE Week = (Select DatePart(week, getdate())-1)
If I can't globally change the settings, than how is it possible to transform the upper clause in such a way, so that to show the results from Monday to Sunday? I am an SQL beginner, searched for an answer in the internet, but couldn't adapt my code. Thank you in advance!
Use DATEPART(ISO_WEEK, ...) after setting SET DATEFIRST 1. This should observe ISO week numbering, as documented in DATEPART documentation.

Query all items for the week in SQL

I have a query that selects all items for the given week and sets their date to be the start day of that week. In some cases the query sets an incorrect date value for the given item and I have traced the problem to be in either DATEDIFF or DATEADD functions.
The query is
SELECT DATEADD(WEEK, DATEDIFF(WEEK, 0, DateTimeValue), 0) AS NewDateTimeValue
Let's take a date March 27 2016 as an example. The DATEDIFF returns value of 6065 and the DATEADD with that value returns March 28 2016.
For the date March 26 2016, the DATEDIFF returns 6064 and the DATEADD March 21, 2016.
To me this sounds like a FirstDayOfWeek issue and that SQL Server thinks Sunday is the first day of a week and thus giving different values for Sunday and for Saturday (March 27, 2016 is Sunday).
I tried to set the first day of the week by
SET DATEFIRST 1
but that didn't make any difference and SQL returned the same results.
So what causes the SQL function to behave like this and any ideas how to fix it?
I found out that DATEDIFF doesn't respect the DATEFIRST setting and always assumes the week starts on Sunday. This is the reason why my sample case works as it works. This question has some suggested workaround: Is it possible to set start of week for T-SQL DATEDIFF function?
This is happening because you are finding the no. of weeks from date 0 to the supplied date. 0 is actually '1900-01-01' which was a Monday. Therefore,DATEDIFF finds the number of completed weeks from this date until the supplied data. Thats why DATEDIFF for March 27 2016 returns 6065 (as it is the end of a week) and March 26 2016 returns 6064 (as it is still not the end of a week).
This is already explained in this link - Get first day of the week

Dynamic Date Range in SSRS or SQL Data Tools builder

I am making a report that will run on the 1st of every month and on the 16th of every month.
If it is running on the 1st I need the #start_date to be the 16th to the last day of the previous month.
If it is running on the 16th I need #start_date to be the 1st of the month through the 15th of the month.
I can think of a couple ways to do this, but I am curious is SSRS/Report Builder/SQL Data Tools builder has an easy method for setting this up.
My option was to make a SQL query that does what I need then plug that into the Get Balues from a query part of the parameter.
If you run the report in the first part of the month then the parameters should be set to the 16th to the end of the previous month; if run in the second part of the month then the parameters should be set to the 1st to the 15th of the current month.
#start_date Default Value expression:
=IIF(Day(Today) >= 16, DateAdd(DateInterval.Day, 1-Day(Today), Today), DateAdd(DateInterval.Month, -1, (DateAdd(DateInterval.Day, 16-Day(Today), Today))))
#end_date Default Value expression:
=IIF(Day(Today) >= 16, DateAdd(DateInterval.Day, 15-Day(Today), Today), DateAdd(DateInterval.Day, -1, (DateAdd(DateInterval.Day, 1-Day(Today), Today))))

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