Skip Holidays in Business day Table - sql

I am using the following script to determine what the business days are for each particular month.
DECLARE #startdate DATETIME
SET #startdate ='20170401'
;
WITH bd AS(
SELECT
DATEADD(DAY,
CASE
(DATEPART(WEEKDAY, DATEADD(MONTH, DATEDIFF(MONTH, 0, #startdate), 0)) + ##DATEFIRST - 1) % 7
WHEN 6 THEN 2
WHEN 7 THEN 1
ELSE 0
END,
DATEADD(MONTH, DATEDIFF(MONTH, 0, #startdate), 0)
) AS bd, 1 AS n
UNION ALL
SELECT DATEADD(DAY,
CASE
(DATEPART(WEEKDAY, bd.bd) + ##DATEFIRST - 1) % 7
WHEN 5 THEN 3
WHEN 6 THEN 2
ELSE 1
END,
bd.bd
) AS db,
bd.n+1
FROM bd WHERE MONTH(bd.bd) = MONTH(#startdate)
)
SELECT * INTO #BD
FROM (
SELECT 'BD'+ CAST(n AS VARCHAR(5)) AS Expected_Date_Rule, bd AS Expected_Calendar_Date
from bd
) AS x
The result of this table works fine. Bd is the the calendar days for the particular month and n is the business day number. The script does its job of not counting the weekend as a business day.
bd n
----------------------- -----------
2017-04-03 00:00:00.000 1
2017-04-04 00:00:00.000 2
2017-04-05 00:00:00.000 3
2017-04-06 00:00:00.000 4
2017-04-07 00:00:00.000 5
2017-04-10 00:00:00.000 6
2017-04-11 00:00:00.000 7
2017-04-12 00:00:00.000 8
2017-04-13 00:00:00.000 9
2017-04-14 00:00:00.000 10
2017-04-17 00:00:00.000 11
2017-04-18 00:00:00.000 12
2017-04-19 00:00:00.000 13
2017-04-20 00:00:00.000 14
2017-04-21 00:00:00.000 15
2017-04-24 00:00:00.000 16
2017-04-25 00:00:00.000 17
2017-04-26 00:00:00.000 18
2017-04-27 00:00:00.000 19
2017-04-28 00:00:00.000 20
2017-05-01 00:00:00.000 21
But then I notice that a potential issue will occur in July where the output will count the 4th of July as BD2 when it should be counted as BD3. Some had created a holiday table that is updated with all the holidays (excuse the bad spelling).
Holiday table
1 2017-01-01 New Year Day
4 2017-01-02 New Year Day-Follow
1 2017-01-16 MArtin Luther King Day
4 2017-01-17 MArtin Luther King Day-Follow
1 2017-02-20 Preseiednt Day
4 2017-02-21 Preseiednt Day-Follow
1 2017-05-29 Memorial Day
4 2017-05-30 Memorial Day-Follow
1 2017-07-04 Independence Day
4 2017-07-05 Independence Day-Follow
1 2017-09-04 Labour Day
4 2017-09-05 Labour Day-Follow
1 2017-10-09 Columbus Day
4 2017-10-10 Columbus Day-Follow
1 2017-11-10 Vetrans Day
4 2017-11-11 Vetrans Day-Follow
1 2017-11-23 ThanksGiving
1 2017-11-24 Day After Thanks Giving
4 2017-11-24 ThanksGiving-Follow
4 2017-11-25 Day After Thanks Giving-Follow
1 2017-12-25 Christmas
4 2017-12-26 Christmas-Follow
I was thinking there may be some way I can update my script to check the holiday table and skip the holiday and dont count it as a business day. Any tips?

Related

SQL Server query Group By Trimester

I'm finding a way to group SQL query by trimester. I have found a way to do it using MySQL on this link.
This is what I'm expecting:
Range Start Range End Count
----------- ---------- -----
2013-09-01 2013-11-26 87
2013-06-01 2013-08-31 92
2013-03-01 2013-05-31 92
2012-12-01 2013-02-28 90
2012-09-01 2012-11-30 91
This is what I have tried:
SELECT MIN(start_date) AS Range_Start, MAX(start_date) AS Range_End, COUNT(ID) AS Total
FROM [dbo].[table]
GROUP BY FLOOR(DATEDIFF(MONTH, DATEADD(DAY, -DAY(start_date)+1, start_date), DATEADD(DAY, -DAY(start_date)+1,getdate())) /3)
ORDER BY 1 ASC
This is what I get:
Range Start Range End Count
----------- ---------- -----
1900-01-01 00:00:00.000 1900-01-01 00:00:00.000 8
1952-01-01 00:00:00.000 1952-01-01 00:00:00.000 2
1954-01-01 00:00:00.000 1954-01-01 00:00:00.000 11
1955-01-01 00:00:00.000 1955-01-01 00:00:00.000 3
1956-01-01 00:00:00.000 1956-01-01 00:00:00.000 2
1957-01-01 00:00:00.000 1957-01-01 00:00:00.000 8
1958-01-01 00:00:00.000 1958-01-01 00:00:00.000 2
1959-01-01 00:00:00.000 1959-01-01 00:00:00.000 5
1960-01-01 00:00:00.000 1960-01-01 00:00:00.000 17
1960-03-17 00:00:00.000 1960-03-17 00:00:00.000 1

How do I retrieve data in Monday to Friday Hourly Format

I have a table that is currently in the following format
ID
Title
CreatedOn
1
Test 1
2021-04-26 08:00:00
2
Test 2
2021-04-26 10:00:00
3
Test 3
2021-04-27 09:00:00
4
Test 4
2021-04-28 14:00:00
5
Test 5
2021-04-28 16:00:00
6
Test 6
2021-04-28 12:00:00
7
Test 7
2021-04-29 13:00:00
8
Test 8
2021-04-30 06:00:00
9
Test 9
2021-05-17 10:00:00
10
Test 10
2021-05-18 19:00:00
11
Test 11
2021-05-18 23:00:00
12
Test 12
2021-05-19 16:00:00
13
Test 13
2021-05-20 07:00:00
14
Test 14
2021-05-21 14:00:00
15
Test 15
2021-05-21 10:00:00
16
Test 16
2021-04-30 10:00:00
What I would like to do is a query that would tell me how many requests have been Monday to Friday per hour. So aggregate all the data into just rows of Monday to Friday.
So the query should return
Day
Hour
Count
Monday
08:00
1
Monday
10:00
2
Tuesday
10:00
1
Tuesday
19:00
1
Tuesday
23:00
1
Wednesday
14:00
1
Wednesday
16:00
2
Wednesday
12:00
1
etc.. How do I achieve this?
So far I have the following
SELECT
DATENAME(WEEK, CreatedOn) AS Week,
DATEPART(Hour, CreatedOn) AS Hour,
COUNT(*) AS Requests
FROM [Enterprise32].[dbo].[nav_EmailEstimateRequests]
where CreatedOn > '2021-01-01'
GROUP BY DATENAME(WK, CreatedOn),DATEPART(Hour, CreatedOn)
ORDER BY DATENAME(WK, CreatedOn);
But the above query returns each week so Week 1 up until Week 21. Please guide me in the right direction.
Thank you!
You want weekday for the date part:
SELECT DATENAME(WEEKDAY, CreatedOn) AS Weekday,
DATEPART(Hour, CreatedOn) AS Hour,
COUNT(*) AS Requests
FROM [Enterprise32].[dbo].[nav_EmailEstimateRequests]
WHERE CreatedOn > '2021-01-01'
GROUP BY DATENAME(WEEKDAY, CreatedOn), DATEPART(Hour, CreatedOn), DATEPART(WEEKDAY, CreatedOn)
ORDER BY DATEPART(WEEKDAY, CreatedOn), Hour;
Note: I included DATEPART(weekday, ) in the GROUP BY, so you could use it in the ORDER BY.

Get quarter start/end dates for more than a year (start year to current year)

I've been trying to get start and end dates range for each quarter given a specific date/year, like this:
SELECT DATEADD(mm, (quarter - 1) * 3, year_date) StartDate,
DATEADD(dd, 0, DATEADD(mm, quarter * 3, year_date)) EndDate
--quarter QuarterNo
FROM
(
SELECT '2012-01-01' year_date
) s CROSS JOIN
(
SELECT 1 quarter UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4
) q
which produces the following output:
2012-01-01 00:00:00 2012-04-01 00:00:00
2012-04-01 00:00:00 2012-07-01 00:00:00
2012-07-01 00:00:00 2012-10-01 00:00:00
2012-10-01 00:00:00 2013-01-01 00:00:00
Problem: I need to do this for a given start_date and end_date, the problem being the end_date=current_day, so how can I achieve this:
2012-01-01 00:00:00 2012-04-01 00:00:00
2012-04-01 00:00:00 2012-07-01 00:00:00
2012-07-01 00:00:00 2012-10-01 00:00:00
2012-10-01 00:00:00 2013-01-01 00:00:00
... ...
2021-01-01 00:00:00 2021-01-06 00:00:00
I think here is what you want to do :
SET startdatevar AS DATEtime = '2020-01-10'
;WITH RECURSIVE cte AS (
SELECT startdatevar AS startdate , DATEADD(QUARTER, 1 , startdatevar) enddate , 1 quarter
UNION ALL
SELECT enddate , CASE WHEN DATEADD(QUARTER, 1 , enddate) > CURRENT_DATE() THEN GETDATE() ELSE DATEADD(QUARTER, 1 , enddate) END enddate, quarter + 1
FROM cte
WHERE
cte.enddate <= CURRENT_DATE()
and quarter < 4
)
SELECT * FROM cte
to use your code , if you want to have more than 4 quarters :
SET quarter_limit = DATEDIFF(quarter , <startdate>,<enddate>)
;WITH RECURSIVE cte(q, qDate,enddate) as
(
select 1,
DATEFROMPARTS(year('2012-01-01'::date), 1, 1) -- First quarter date
,time_slice('2012-01-01'::date, 3, 'MONTH', 'END')
UNION ALL
select q+1,
DATEADD(q, 1, qdate) -- next quarter start date
,time_slice(qdate::date, (q+1)*3, 'MONTH', 'END')
from cte
where q < quarter_limit -- limiting the number of next quarters
AND cte.endDate <= <enddate>
)
SELECT * FROM cte
After #eshirvana's answer, I came up with this slightly change after your answer:
WITH RECURSIVE cte(q, qDate,enddate) as
(
select 1,
DATEFROMPARTS(year('2012-01-01'::date), 1, 1) -- First quarter date
,time_slice('2012-01-01'::date, 3, 'MONTH', 'END')
UNION ALL
select q+1,
DATEADD(q, 1, qdate) -- next quarter start date
,time_slice(qdate::date, (q+1)*3, 'MONTH', 'END')
from cte
where q <4 -- limiting the number of next quarters
AND cte.endDate <= CURRENT_DATE()
)
SELECT * FROM cte
Which works fine for whatever year I pass there (2012 will produce 4 records, 2021 just one, since we're still on the first quarter right now).
[EDIT]: it still doesn't work as expected after your 2nd code sugestion:
WITH RECURSIVE cte(q, qDate,enddate) as
(
select 1,
DATEFROMPARTS(year('2012-01-01'::date), 1, 1) -- First quarter date
,CASE WHEN time_slice('2012-01-01'::date, 3, 'MONTH', 'END') > CURRENT_DATE
THEN current_date
ELSE time_slice('2012-01-01'::date, 3, 'MONTH', 'END')
END
UNION ALL
select q+1,
DATEADD(q, 1, qdate) -- next quarter start date
,time_slice(qdate::date, (q+1)*3, 'MONTH', 'END')
from cte
where q < DATEDIFF(quarter , '2012-01-01'::date,'2021-01-06'::date)
AND cte.endDate <= '2021-01-06'::date
)
SELECT * FROM cte
is outputing this:
Sorry #eshirvana, it doesn't work as expected though. It all goes well to some point, but it's not returning all the records. Instead, it produces less records and wrong one, like this:
1 2012-01-01 2012-04-01
2 2012-04-01 2012-07-01
3 2012-07-01 2012-10-01
4 2012-10-01 2013-01-01
5 2013-01-01 2013-10-01
6 2013-04-01 2013-07-01
7 2013-07-01 2013-10-01
8 2013-10-01 2014-01-01
9 2014-01-01 2015-01-01
10 2014-04-01 2015-01-01
11 2014-07-01 2016-10-01
12 2014-10-01 2015-01-01
13 2015-01-01 2015-07-01
14 2015-04-01 2015-07-01
15 2015-07-01 2018-10-01
16 2015-10-01 2018-01-01
17 2016-01-01 2016-10-01
18 2016-04-01 2019-07-01
19 2016-07-01 2017-07-01
20 2016-10-01 2020-01-01
21 2017-01-01 2017-04-01
22 2017-04-01 2019-07-01
23 2017-07-01 2021-10-01
Although my logic it's still not ok for not printing just Q1 dates for 2021, could this output issues be related to date format or something?
Now, it seems to be working, at least for 2012-01-01 till today (2021-01-06).
The code :
WITH RECURSIVE cte(q, qDate,enddate) as
(
select
-- it might not be the first quarter, so better to protect that:
quarter('2012-01-01'::date)::numeric
, DATEFROMPARTS(year('2012-01-01'::date), 1, 1) -- First quarter date
, CASE WHEN time_slice('2012-01-01'::date, 3, 'MONTH', 'END') > '2021-01-06'::date
THEN '2021-01-06'::date
ELSE time_slice('2012-01-01'::date, 3, 'MONTH', 'END')
END
UNION ALL
select q+1
, DATEADD(q, 1, qdate) -- next quarter start date
,CASE WHEN time_slice(DATEADD(q, 1, qdate), 3, 'MONTH', 'END')> '2021-01-06'::date
THEN '2021-01-06'::date
ELSE time_slice(DATEADD(q, 1, qdate), 3, 'MONTH', 'END')
END
from cte
where q <= DATEDIFF(quarter , '2012-01-01'::date,'2021-01-06'::date)
AND cte.endDate <= '2021-01-06'::date
)
SELECT * FROM cte
The output:
1 2012-01-01 2012-04-01
2 2012-04-01 2012-07-01
3 2012-07-01 2012-10-01
4 2012-10-01 2013-01-01
5 2013-01-01 2013-04-01
6 2013-04-01 2013-07-01
7 2013-07-01 2013-10-01
8 2013-10-01 2014-01-01
9 2014-01-01 2014-04-01
10 2014-04-01 2014-07-01
11 2014-07-01 2014-10-01
12 2014-10-01 2015-01-01
13 2015-01-01 2015-04-01
14 2015-04-01 2015-07-01
15 2015-07-01 2015-10-01
16 2015-10-01 2016-01-01
17 2016-01-01 2016-04-01
18 2016-04-01 2016-07-01
19 2016-07-01 2016-10-01
20 2016-10-01 2017-01-01
21 2017-01-01 2017-04-01
22 2017-04-01 2017-07-01
23 2017-07-01 2017-10-01
24 2017-10-01 2018-01-01
25 2018-01-01 2018-04-01
26 2018-04-01 2018-07-01
27 2018-07-01 2018-10-01
28 2018-10-01 2019-01-01
29 2019-01-01 2019-04-01
30 2019-04-01 2019-07-01
31 2019-07-01 2019-10-01
32 2019-10-01 2020-01-01
33 2020-01-01 2020-04-01
34 2020-04-01 2020-07-01
35 2020-07-01 2020-10-01
36 2020-10-01 2021-01-01
37 2021-01-01 2021-01-06
In case you're wondering: yes, the idea is to present the end_date as last_day of the month+one. But it could easily be adapted.
It's not pretty, but I think it's somehow easy to understand.

Group dates by 7 days excluding specific dates

I need query, where I could group dates by every 7 days from beginning of the month. The problem is I have to exclude some days, specifically days before/after holidays and holidays. In my DateDay dimension there's a column, thats indicates which type of day it is. Example of calendar for November:
DTD_GID DTD_Date DTD_DayType
20161101 2016-11-01 2 --holiday was on 2016-10-31
20161102 2016-11-02 0
20161103 2016-11-03 0
20161104 2016-11-04 0
20161105 2016-11-05 0
20161106 2016-11-06 0
20161107 2016-11-07 0
20161108 2016-11-08 0
20161109 2016-11-09 0
20161110 2016-11-10 2
20161111 2016-11-11 1--public holiday
20161112 2016-11-12 2
20161113 2016-11-13 0
20161114 2016-11-14 0
20161115 2016-11-15 0
20161116 2016-11-16 0
20161117 2016-11-17 0
20161118 2016-11-18 0
20161119 2016-11-19 0
20161120 2016-11-20 0
20161121 2016-11-21 0
20161122 2016-11-22 0
20161123 2016-11-23 0
20161124 2016-11-24 0
20161125 2016-11-25 0
20161126 2016-11-26 0
20161127 2016-11-27 0
20161128 2016-11-28 0
20161129 2016-11-29 0
20161130 2016-11-30 0
I need to group it like that:
1: 2016-11-02 - 2016-11-08 (inclusive)
2: 2016-11-13 - 2016-11-19
3: 2016-11-20 - 2016-11-26
If such group would have less than 7 days, it shouldn't be returned by query.
Let me know if you need more details.
EDIT: I'm not sure if it will help, but I wrote query that's counting proper days in weeks
SELECT
DTD_DTMGID
,CONVERT(VARCHAR(5), DATEADD(WK, Week, 0), 103) + ' - ' + CONVERT(VARCHAR(5), DATEADD(DD, 6, DATEADD(WK, Week, 0)), 103) AS Week
,Cnt
FROM (
SELECT
DTD_DTMGID
, DATEDIFF(WK, 0, DTD_DATE) AS Week
, COUNT(*) AS Cnt
FROM DIM_DateDay
WHERE DTD_DayType = 0
GROUP BY DTD_DTMGID ,DATEDIFF(WK, 0, DTD_DATE)
) AS X
ORDER BY DTD_DTMGID
and result:
DTD_DTMGID Week Cnt
201301 31/12 - 06/01 2
201301 07/01 - 13/01 5
201301 14/01 - 20/01 7
201301 21/01 - 27/01 7
201301 28/01 - 03/02 5
201302 28/01 - 03/02 2
EDIT2: As output I expect ID's of days that are in those groups. As ID's I mean DTD_GID column which is primary key in my DateDay dimension.
So for group 1) I'd get following list:
20161102
20161103
20161104
20161105
20161106
20161107
20161108
Here is one solution that gives you start and end date of each 7-day range:
WITH CTE1 AS (
SELECT DTD_Date, DATEDIFF(DAY, ROW_NUMBER() OVER (ORDER BY DTD_Date), DTD_Date) AS Group1
FROM #Table1
WHERE DTD_DayType = 0
), CTE2 AS (
SELECT DTD_Date, Group1, (ROW_NUMBER() OVER (PARTITION BY Group1 ORDER BY Group1) - 1) / 7 AS Group2
FROM CTE1
)
SELECT MIN(DTD_Date) AS DTD_From, MAX(DTD_Date) AS DTD_Upto, COUNT(DTD_Date) AS C
FROM CTE2
GROUP BY Group1, Group2
ORDER BY DTD_From
-- HAVING COUNT(*) >= 7
Output:
DTD_From | DTD_Upto | C
-----------+------------+--
2016-11-02 | 2016-11-08 | 7
2016-11-09 | 2016-11-09 | 1
2016-11-13 | 2016-11-19 | 7
2016-11-20 | 2016-11-26 | 7
2016-11-27 | 2016-11-30 | 4
Here is how it works:
The first CTE removes holidays and assigns a group number to remaining rows. Consecutive dates get same group number (see this question).
The second CTE assigns another group number to each row in each group. Row number 1-7 get 0, 8-14 get 1, and so on.
Finally you group the results by the group numbers.

How to Update Week Number in SQL?

I have a following which are displayed order by date. I want to group each weekseries as below.
Select tq.ID,
CONVERT(VARCHAR(10),tq.DateCreated,101)WeekDate,
DATENAME(WEEKDAY,tq.DateCreated)WeekDays,
CASE When DATEPART(WEEKDAY,tq.DateCreated)-1=0 THEN 7 ELSE DATEPART(WEEKDAY,tq.DateCreated)-1 END as WeekSerial
From #temp tq
Current Data:
ID WeekDate WeekDays WeekSerial WeekNumber
56 2012-03-01 00:00:00.000 Thursday 4 NULL
57 2012-03-02 00:00:00.000 Friday 5 NULL
58 2012-03-03 00:00:00.000 Saturday 6 NULL
59 2012-03-04 00:00:00.000 Sunday 7 NULL
62 2012-03-05 00:00:00.000 Monday 1 NULL
63 2012-03-06 00:00:00.000 Tuesday 2 NULL
64 2012-03-07 00:00:00.000 Wednesday 3 NULL
65 2012-03-08 00:00:00.000 Thursday 4 NULL
67 2012-03-09 00:00:00.000 Friday 5 NULL
68 2012-03-10 00:00:00.000 Saturday 6 NULL
69 2012-03-11 00:00:00.000 Sunday 7 NULL
70 2012-03-12 00:00:00.000 Monday 1 NULL
71 2012-03-13 00:00:00.000 Tuesday 2 NULL
73 2012-03-14 00:00:00.000 Wednesday 3 NULL
74 2012-03-15 00:00:00.000 Thursday 4 NULL
76 2012-03-16 00:00:00.000 Friday 5 NULL
77 2012-03-17 00:00:00.000 Saturday 6 NULL
78 2012-03-18 00:00:00.000 Sunday 7 NULL
Required Data:
ID WeekDate WeekDays WeekSerial WeekNumber
56 2012-03-01 00:00:00.000 Thursday 4 1
57 2012-03-02 00:00:00.000 Friday 5 1
58 2012-03-03 00:00:00.000 Saturday 6 1
59 2012-03-04 00:00:00.000 Sunday 7 1
62 2012-03-05 00:00:00.000 Monday 1 2
63 2012-03-06 00:00:00.000 Tuesday 2 2
64 2012-03-07 00:00:00.000 Wednesday 3 2
65 2012-03-08 00:00:00.000 Thursday 4 2
67 2012-03-09 00:00:00.000 Friday 5 2
68 2012-03-10 00:00:00.000 Saturday 6 2
69 2012-03-11 00:00:00.000 Sunday 7 2
70 2012-03-12 00:00:00.000 Monday 1 3
71 2012-03-13 00:00:00.000 Tuesday 2 3
73 2012-03-14 00:00:00.000 Wednesday 3 3
74 2012-03-15 00:00:00.000 Thursday 4 3
76 2012-03-16 00:00:00.000 Friday 5 3
77 2012-03-17 00:00:00.000 Saturday 6 3
78 2012-03-18 00:00:00.000 Sunday 7 3
So, I want to group these values under weeknumber which must start from 1 for WeekSerial number ranges from 1 to 7.
NOTE: The week day starts from Monday to Sunday so its numbered from 1 through 7. i.e 1=Monday, 2=Tuesday and so on...!
Update:
INSERT INTO #Temp(KioskCount,KioskAmount,KioskAverage,WeekDate,WeekDays,WeekSerial)
Select COUNT(tq.quoteid)KioskCount,
SUM(tq.PriceQuote) [KioskAmount],
SUM(tq.PriceQuote) / COUNT(tq.QuoteID) [KioskAverage],
CONVERT(VARCHAR(10),tq.DateCreated,101)WeekDate,
DATENAME(WEEKDAY,tq.DateCreated)WeekDays,
CASE When DATEPART(WEEKDAY,tq.DateCreated)-1=0 THEN 7 ELSE DATEPART(WEEKDAY,tq.DateCreated)-1 END as WeekSerial
from tbl_Quotes tq
where
tq.QuoteStatusID <> 12 --remove void transactions
group by CONVERT(VARCHAR(10),tq.DateCreated,101),DATENAME(WEEKDAY,tq.DateCreated),DATEPART(WEEKDAY,tq.DateCreated)-1
order by 4
It is unclear actually what did you expect
You have already a WeekDate filed i think the date are correct and based on that you are filled your weekday field
then simply you can loop through the dates and update your week number using the WeekDate
i can provide an example with that
DECLARE #DATE DATETIME
DECLARE #count int
DECLARE #i int
SET #i=56// you can find your first id via query too
SET #count=(select COUNT(WeekDays) from tablename)
WHILE #i<=#count
BEGIN
SET #DATE =(select WeekDate from tablename where ID=#i)
update tablename set WeekNumber=(
SELECT DATEPART(WEEK, #DATE) -
DATEPART(WEEK, DATEADD(MM, DATEDIFF(MM,0,#DATE), 0))+ 1 AS WEEK_OF_MONTH)
where ID=#i
set #i=#i + 1
END;
it will update all your weeknumber field with corresponding number
Probably this helps you:
First you need to check the first of the day in your database
SELECT ##DATEFIRST
By default SUNDAY is first day of week (US). So you need to change it to 1 (Monday)
SET DATEFIRST 1
More inforamtion about SET DATEFIRST
In SQL Server by using DATEPART built-in function you can get the number of week in a year
SELECT DATAPART(WEEK, WeekDate)
Also you can get YEAR of your selected datetime
SELECT DATAPART(YEAR, WeekDate)
If you run these two queries for your first row (Let's say Week number 1)
SELECT DATEPART(WEEK, '2012-03-01 00:00:00.000') -- Output = 10
SELECT DATEPART(YEAR, '2012-03-01 00:00:00.000') -- Output = 2012
But this week should be your week number 1.
So you can easily subtract 2012 from your YEAR then multiply it by 52 (because we have 52 weeks in a year)
Substract 9 from your WEEKNUMBER
Add the numbers you get from above
(YEAR - 2012) * 52 + (WEEK - 9)
So by running this you can get the actual result
SELECT (DATEPART(YEAR, WeekDate) - 2012) * 52 + DATEPART(WEEK, WeekDate) - 9 AS WeekNumber
FROM yourTable