Calculating week number SQL Server - sql-server-2008

I have a query where I need to calculate the week number based on the fiscal start of the year occurring on 01.07.YEAR
The problem I have is that when it goes to 30 Days of a calendar year I don't get the correct result and so I need to amend my script. I want a query that returns the correct week number regardless of what month I am in.
I have a calendar table populated; I add 18 months to the current date which give me the period and so I tried to do the same to the week but I am going around in circles.
Below is the code I am using:
SET DATEFIRST 1;
SELECT
[date],
DATEPART(wk, DATEADD(MONTH, 18, DATEADD(dd, -2, [date]))) 'FWeek',
LEFT(CONVERT(varchar, DATEADD(MONTH, 18, [date]), 112), 6) AS 'Period',
DATENAME(dw, [date]) AS 'Day'
FROM [dbo].[DP_PERIOD_DATES]
WHERE [date] >= '01/11/2018'
AND [date] < '04-01-2019'
ORDER BY [date] DESC

Try datediff to get the number of weeks from 1/7/x.
The extra datediff is to get the first of the year and add 6 to get the 7th of the year.
SELECT [date],
DateDiff(wk,
--JANUARY 7th of Current Year
DATEADD(yy, DATEDIFF(yy, 0, DATEADD(m,18,[date])), 0)+6
, DATEADD(m,18,[date]))
FROM [dbo].[DP_PERIOD_DATES]
WHERE [date] >= '01/11/2018'
AND [date] < '04-01-2019'
ORDER BY [date] DESC

SET FWEEK = DATENAME(yy, (DATEADD(month, 18, [date]))) + RIGHT('00'+DATENAME(dy,(datepart(DAYOFYEAR,DATEDIFF(DY,0,[date])/7*7+547)+5)/7),2)
, period = LEFT(CONVERT(varchar, DATEADD(month, 18, [date]),112),6)
Thanks Paul for all your help; it really wasnt easy as trying to apply someone elses logic to a date. I got it working using the above code in case anyone is looking for the same type of answer in the future

Related

Get weeks in a month using SQL Server 2008

This year, August contains week #'s 31, 32, 33 & 34.
How can I make a query that gets all returns from each week in the month(8)?
Example:
select sum(a) as MyTot
from MyTable
where week numbers are included in month
Clear as mud?
I can get the return for each week because there is a field with the week number in it. I need to sum all the weeks that are in any given month.
Thanks,
You could create a calendar table, containing all kinds of data about dates - weekday, week number, day of year, day of month, month name, month number etc'. Then you can join your current table with the calendar table, filtering by the relevant month.
In fact, this might be a very useful thing to have, as pointed out by Aaron Bertrand in his Creating a date dimension or calendar table in SQL Server article.
Another option is to compute the first and last date of the month, get the week number of these dates, and use that to select the data from your table:
DECLARE #StartDate date = DATEADD(Month, DATEDIFF(Month, 0, GetDate()), 0)
DECLARE #EndDate date = DATEADD(Day, -1, DATEADD(Month, 1, #StartDate))
SELECT SUM(a) as MyTot
FROM MyTable
WHERE weekNumber >= DATEPART(WEEK, #StartDate)
AND weekNumber <= DATEPART(WEEK, #EndDate)
Please note, however, that the DATEPART(WEEK, #Date) return value depends on the value set by SET DATEFIRST. You might also want to look at ISO_WEEK.

How to get current week data till today's date using query?

How to fetch current week data till today's date ?
Example - Current week start from 2017-08-01 to 2017-08-07 and today date is 2017-08-03. I want to fetch data from 2017-08-01 to 2017-08-03 using query.
This is query -
SELECT *
FROM user_data
WHERE YEARWEEK(`date`, 1) = YEARWEEK(CURDATE(), 1)
I have resolved my problem.
SELECT *
FROM current_week
WHERE YEARWEEK(`dt`, 1) = YEARWEEK(CURDATE(), 1) and dt <= curdate() order by dt
This is working fine.
This one gets tricky in the last and first weeks of calendar years.
First you need to decide whether your week starts on Sunday or Monday. That is based on your national jurisdiction's business practices. In North America, it's generally Sunday. In Europe it is sometimes Monday.
You need an expression that computes the first moment of a calendar week based on a date.
This is such an expression for weeks starting Sunday.
FROM_DAYS(TO_DAYS(CURDATE()) -MOD(TO_DAYS(CURDATE()) -1, 7))
This is it for weeks starting Monday. (Notice the -2.)
FROM_DAYS(TO_DAYS(CURDATE()) -MOD(TO_DAYS(CURDATE()) -2, 7))
Now you can select stuff from your table that's in the current week.
SELECT whatever, whatever
FROM user_data
WHERE `date` >= FROM_DAYS(TO_DAYS(CURDATE()) -MOD(TO_DAYS(CURDATE()) -1, 7))
If you want stuff from the week before the current week use this
SELECT whatever, whatever
FROM user_data
WHERE `date` >= FROM_DAYS(TO_DAYS(CURDATE()) -MOD(TO_DAYS(CURDATE()) -1, 7)) - INTERVAL 7 DAY
AND `date` < FROM_DAYS(TO_DAYS(CURDATE()) -MOD(TO_DAYS(CURDATE()) -1, 7))

SSRS Expression - Find First Day of Week From Week value

I've got an SSRS report that returns unique login count to our VDI Pools broken down by week.
For example for January it would read:
Week # of Logins
2015_JANUARY_WEEK_NO_1 3
2015_JANUARY_WEEK_NO_2 49
I'm using the Week column to link to another report that'll display the selected week's logins so I have to get the first day of the selected week and the last day of the select week and pass them to the other report as parameters.
I know how to get pull the year and week # from the Week column.
=Mid(Fields!Week.Value,1,4)
gives me the year and
=Trim(Mid(Fields!Week.Value,Len(Fields!Week.Value),Len(Fields!Week.Value)))
gives me the week.
I found this T-SQL that works:
DECLARE #WeekNum INT
, #YearNum char(4);
SELECT #WeekNum = 2
, #YearNum = 2015
-- once you have the #WeekNum and #YearNum set, the following calculates the date range.
SELECT DATEADD(wk, DATEDIFF(wk, 6, '1/1/' + #YearNum) + (#WeekNum-1), 6) AS StartOfWeek;
SELECT DATEADD(wk, DATEDIFF(wk, 5, '1/1/' + #YearNum) + (#WeekNum-1), 5) AS EndOfWeek;
but I cannot figure out how to turn that into an expression that doesn't throw an error.
This is what I've got so far:
=DateAdd("w", DateDiff("w", 6, '1/1/' + (Mid(Fields!Week.Value,1,4))) + (Trim(Mid(Fields!Week.Value,Len(Fields!Week.Value),Len(Fields!Week.Value)))
- 1), 6)
and when I try to run the report in design view it returns an Expression expected error.
Edit
Sorry, I guess I should've posted my original query that's populating the report. Here it is below:
SELECT Convert(varchar(20),UPPER(DATENAME(YEAR, Time)))
+'_'+CONVERT(varchar(20),UPPER(DATENAME(MONTH, Time)))
+'_WEEK_NO_'+CONVERT(varchar(10),(DAY(Time)
+ (DATEPART(DW, DATEADD (MONTH, DATEDIFF (MONTH, 0, Time), 0))-1) -1)/7 + 1) as 'Week'
, Count(DISTINCT SUBSTRING(ModuleAndEventText,LEN('User ') + 2
, CHARINDEX(' requested', ModuleAndEventText) - LEN('User ') - 2)) as WeekCount
FROM VE1_UserLogins
WHERE DesktopId = #Pool
AND ([Time] BETWEEN (#StartDate) and (DATEADD(ms, -1, #EndDate +1)))
GROUP BY Convert(varchar(20),UPPER(DATENAME(YEAR, Time)))
+'_'+CONVERT(varchar(20),UPPER(DATENAME(MONTH, Time)))
+'_WEEK_NO_'+CONVERT(varchar(10),(DAY(Time)
+ (DATEPART(DW, DATEADD (MONTH, DATEDIFF (MONTH, 0, Time), 0))-1) -1)/7 + 1),YEAR(Time),MONTH(Time)
ORDER BY YEAR(Time), MONTH(Time), Week
I am assuming your Fields!Week.Value is string in date format like MM/dd/yyyy or something similar so if you want to get the start of that week Sunday as first day and Saturday as last day and you want to get there date then you should use below expression,
For start of week,
=DateAdd("d",1- DatePart("w", CDate(Fields!WeekDate.Value)), CDate(Fields!WeekDate.Value))
For end of week,
=DateAdd("d", 7 - DatePart("w", CDate(Fields!WeekDate.Value)), CDate(Fields!WeekDate.Value))
----------
UPDATE
Now there are two ways to achieve what you want
1)Calculate start of week and end of week at the sql and get the result to directly display on repott
2) Get time field from the sql and set expression in the SSRS
For the first way to achieve you need to add these two lines in your select sql statement
DATEADD(dd, -(DATEPART(dw, MIN(Time))-1),MIN(Time)) AS 'StartOfWeek'
,DATEADD(dd, 7-(DATEPART(dw, MIN(Time))), MIN(Time)) AS 'EndOfWeek'
Second way to achieve is
Update your Sql statement to get the date part and then include that date into the above given expression.
So for you your query you need to add,
,MIN(Time) AS WeekDate
Then you can use the above expression with using the incoming field WeekDate as input(I have updated the expression).
But, If you have no actual need for the date other than calculating the start and end of week then use the first method to get the data from the sql server as formatted.

how to show week over week in sql

I need to display two calculated columns of the sum of GP for one week and in the other column previous
I think my way is right but i am missing something
I am trying to get my result to be like this::
|WEEK|JP|AUS|GB|
|PREV|22|32|23|
|CUR|12|15|12|
my sql is this I believe I may need to pivot the data
SELECT
(SUM(`GP`), `gptw`)
FROM
(SELECT
`GP`,
`Country`
FROM
`Finance`
WHERE DATE >= CURDATE() - INTERVAL DAYOFWEEK(CURDATE()) + 6 DAY
AND DATE < CURDATE() - INTERVAL DAYOFWEEK(CURDATE()) - 1 DAY
GROUP BY `Country`) AS lastweeek
INNER JOIN
(SELECT
SUM(`GP`) AS `gptw`,
`Country`
FROM
Finance
WHERE DATEDIFF(NOW(), `date`) < 4
GROUP BY `Country`) AS `thisweek`
Nitpick: DATE is a poor choice of column name because it's a reserved SQL word.
There are four levels of logic here.
First, you need to have working logic to figure out which week each day is in.
Second, you need to select the correct range of DATE values.
Third, you need to get the GROUP BY logic right.
Fourth, you need to pivot your result set to get this week and last week into the same row. This pivoting should be the subject of another question.
First, this expression will turn any DATETIME value into the preceding Sunday.
FROM_DAYS(TO_DAYS(value) -MOD(TO_DAYS(value) -1, 7))
Second, here's what you need to select two weeks (last week and this week)
WHERE `DATE` >= FROM_DAYS(TO_DAYS(NOW()) -MOD(TO_DAYS(NOW()) -1, 7)) - INTERVAL 7 DAY
AND `DATE` < FROM_DAYS(TO_DAYS(NOW()) -MOD(TO_DAYS(NOW()) -1, 7)) + INTERVAL 7 DAY
This gets the range of dates starting with the Sunday before last Sunday, and ending the moment before the Sunday after this Sunday, a two week range.
Third, you need to group correctly. In your schema, group by week and by country. It would go something like this:
SELECT SUM(`GP`) AS GP,
`Country`,
FROM_DAYS(TO_DAYS(`DATE`) -MOD(`DATE`) -1, 7)) AS week_beginning
FROM `Finance`
WHERE `DATE` >= FROM_DAYS(TO_DAYS(NOW()) -MOD(TO_DAYS(NOW()) -1, 7)) - INTERVAL 7 DAY
AND `DATE` < FROM_DAYS(TO_DAYS(NOW()) -MOD(TO_DAYS(NOW()) -1, 7)) + INTERVAL 7 DAY
GROUP BY `Country`, FROM_DAYS(TO_DAYS(`DATE`) -MOD(`DATE`) -1, 7))
ORDER BY `Country`, FROM_DAYS(TO_DAYS(`DATE`) -MOD(`DATE`) -1, 7))
This will give you two rows per country, one for the week_beginning a week ago, and one for the current week. This could do the trick for you. If not, you can pivot this query's results to arrange the rows the way you want them. That should be the subject of another question.
Finally, if you can define stored functions in your MySQL instance, you should define the function TRUNC_SUNDAY. Then you can write your query more readably like this:
SELECT SUM(`GP`) AS GP,
`Country`,
TRUNC_SUNDAY(`DATE`) AS week_beginning
FROM `Finance`
WHERE `DATE` >= TRUNC_SUNDAY(NOW()) - INTERVAL 7 DAY
AND `DATE` < TRUNC_SUNDAY(NOW()) + INTERVAL 7 DAY
GROUP BY `Country`, TRUNC_SUNDAY(`DATE`)
ORDER BY `Country`, TRUNC_SUNDAY(`DATE`)
Here is SQL code to define the stored TRUNC_SUNDAY function you need:
DELIMITER $$
DROP FUNCTION IF EXISTS `TRUNC_SUNDAY`$$
CREATE FUNCTION `TRUNC_SUNDAY`(datestamp DATETIME)
RETURNS DATE
NO SQL
DETERMINISTIC
COMMENT 'returns preceding Sunday'
RETURN FROM_DAYS(TO_DAYS(datestamp) -MOD(TO_DAYS(datestamp) -1, 7))$$
DELIMITER ;
You can find a detailed writeup of this technique, including a TRUNC_MONDAY function, here. You'll need the TRUNC_MONDAY function if your weekdays are defined as starting on Monday rather than Sunday. http://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/

How to get week number of the month from the date in sql server 2008

In SQL Statement in microsoft sql server, there is a built-in function to get week number but it is the week of the year.
Select DatePart(week, '2012/11/30') // **returns 48**
The returned value 48 is the week number of the year.
Instead of 48, I want to get 1, 2, 3 or 4 (week number of the month). I think the week number of the month can be achieved by modules with Month Number of this week. For e.g.
Select DATEPART(week, '2012/11/30')%MONTH('2012/11/30')
But I want to know is there other built-in functions to get WeekNumber of the month in MS SQL SERVER.
Here are 2 different ways, both are assuming the week starts on monday
If you want weeks to be whole, so they belong to the month in which they start:
So saturday 2012-09-01 and sunday 2012-09-02 is week 4 and monday 2012-09-03 is week 1 use this:
DECLARE #date date = '2012-09-01'
SELECT (day(datediff(d,0,#date)/7*7)-1)/7+1
If your weeks cut on monthchange so saturday 2012-09-01 and sunday 2012-09-02 is week 1 and monday 2012-09-03 is week 2 use this:
DECLARE #date date = '2012-09-01'
SELECT
datediff(ww,datediff(d,0,dateadd(m,datediff(m,7,#date),0)
)/7*7,dateadd(d,-1,#date))+1
I received an email from Gerald. He pointed out a flaw in the second method. This should be fixed now
I received an email from Ben Wilkins. He pointed out a flaw in the first method. This should be fixed now
DECLARE #DATE DATETIME
SET #DATE = '2013-08-04'
SELECT DATEPART(WEEK, #DATE) -
DATEPART(WEEK, DATEADD(MM, DATEDIFF(MM,0,#DATE), 0))+ 1 AS WEEK_OF_MONTH
No built-in function. It depends what you mean by week of month. You might mean whether it's in the first 7 days (week 1), the second 7 days (week 2), etc. In that case it would just be
(DATEPART(day,#Date)-1)/7 + 1
If you want to use the same week numbering as is used with DATEPART(week,), you could use the difference between the week numbers of the first of the month and the date in question (+1):
(DATEPART(week,#Date)- DATEPART(week,DATEADD(m, DATEDIFF(m, 0, #Date), 0))) + 1
Or, you might need something else, depending on what you mean by the week number.
Just look at the date and see what range it falls in.
Range 1-7 is the 1st week, Range 8-14 is the 2nd week, etc.
SELECT
CASE WHEN DATEPART(day,yourdate) < 8 THEN '1'
ELSE CASE WHEN DATEPART(day,yourdate) < 15 then '2'
ELSE CASE WHEN DATEPART(day,yourdate) < 22 then '3'
ELSE CASE WHEN DATEPART(day,yourdate) < 29 then '4'
ELSE '5'
END
END
END
END
Similar to the second solution, less code:
declare #date datetime = '2014-03-31'
SELECT DATEDIFF(week,0,#date) - (DATEDIFF(week,0,DATEADD(dd, -DAY(#date)+1, #date))-1)
Check this out... its working fine.
declare #date as datetime = '2014-03-10'
select DATEPART(week,#date) - DATEPART(week,cast(cast(year(#date) as varchar(4))+'-' + cast(month(#date) as varchar(2)) + '-01' as datetime))+1
WeekMonth = CASE WHEN (DATEPART(day,TestDate) - datepart(dw,TestDate))>= 22 THEN '5'
WHEN (DATEPART(day,TestDate) - datepart(dw,TestDate))>= 15 THEN '4'
WHEN (DATEPART(day,TestDate) - datepart(dw,TestDate))>= 8 THEN '3'
WHEN (DATEPART(day,TestDate) - datepart(dw,TestDate))>= 1 THEN '2'
ELSE '1'
END
There is no inbuilt function to get you the week number. I dont think dividing will help you anyway as the number of weeks in a month is not constant.
http://msdn.microsoft.com/en-us/library/bb675168.aspx
I guess you can divide the number(48) by 4 and take the modules of the same and project that as the week number of that month, by adding one to the result.
Here's a suggestion for getting the first and last days of the week for a month:
-- Build a temp table with all the dates of the month
drop table #tmp_datesforMonth
go
declare #begDate datetime
declare #endDate datetime
set #begDate = '6/1/13'
set #endDate = '6/30/13';
WITH N(n) AS
( SELECT 0
UNION ALL
SELECT n+1
FROM N
WHERE n <= datepart(dd,#enddate)
)
SELECT DATEADD(dd,n,#BegDate) as dDate
into #tmp_datesforMonth
FROM N
WHERE MONTH(DATEADD(dd,n,#BegDate)) = MONTH(#BegDate)
--- pull results showing the weeks' dates and the week # for the month (not the week # for the current month)
select MIN(dDate) as BegOfWeek
, MAX(dDate) as EndOfWeek
, datediff(week, dateadd(week, datediff(week, 0, dateadd(month, datediff(month, 0, dDate), 0)), 0), dDate) as WeekNumForMonth
from #tmp_datesforMonth
group by datediff(week, dateadd(week, datediff(week, 0, dateadd(month, datediff(month, 0, dDate), 0)), 0), dDate)
order by 3, 1
A dirty but easy one liner using Dense_Rank function. Performance WILL suffer, but effective none the less.
DENSE_RANK()over(Partition by Month(yourdate),Year(yourdate) Order by Datepart(week,yourdate) asc) as Week
Here is the query that brings the week number on whatever the startday and endday of the week it may be.
SET DATEFIRST 2
DECLARE #FROMDATE DATE='12-JAN-2015'
-- Get the first day of month
DECLARE #ALLDATE DATE=DATEADD(month, DATEDIFF(month, 0, #FROMDATE), 0)
DECLARE #FIRSTDATE DATE
;WITH CTE as
(
-- Get all dates in that month
SELECT 1 RNO,CAST(#ALLDATE AS DATE) as DATES
UNION ALL
SELECT RNO+1, DATEADD(DAY,1,DATES )
FROM CTE
WHERE DATES < DATEADD(MONTH,1,#ALLDATE)
)
-- Retrieves the first day of week, ie, if first day of week is Tuesday, it selects first Tuesday
SELECT TOP 1 #FIRSTDATE = DATES
FROM CTE
WHERE DATEPART(W,DATES)=1
SELECT (DATEDIFF(DAY,#FIRSTDATE,#FROMDATE)/7)+1 WEEKNO
For more information I have answered for the below question. Can check that.
How do I find week number of a date according to DATEFIRST
floor((day(#DateValue)-1)/7)+1
Here you go....
Im using the code below..
DATEPART(WK,#DATE_INSERT) - DATEPART(WK,DATEADD(DAY,1,DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#DATE_INSERT),0)))) + 1
Try Below Code:
declare #dt datetime='2018-03-15 05:16:00.000'
IF (Select (DatePart(DAY,#dt)%7))>0
Select (DatePart(DAY,#dt)/7) +1
ELSE
Select (DatePart(DAY,#dt)/7)
There is an inbuilt option to get the week number of the year
**select datepart(week,getdate())**
You can simply get week number by getting minimum week number of month and deduct it from week number. Suppose you have a table with dates
select
emp_id, dt , datepart(wk,dt) - (select min(datepart(wk,dt))
from
workdates ) + 1 from workdates
Solution:
declare #dt datetime='2018-03-31 05:16:00.000'
IF (Select (DatePart(DAY,#dt)%7))>0
Select (DatePart(DAY,#dt)/7) +1
ELSE
Select (DatePart(DAY,#dt)/7)
declare #end_date datetime = '2019-02-28';
select datepart(week, #end_date) - datepart(week, convert(datetime, substring(convert(nvarchar, convert(datetime, #end_date), 127), 1, 8) + '01')) + 1 [Week of Month];
Here is the tried and tested solution for this query in any situation - like if 1st of the month is on Friday , then also this will work -
select (DATEPART(wk,#date_given)-DATEPART(wk,dateadd(d,1-day(#date_given),#date_given)))+1
above are some solutions which will fail if the month's first date is on Friday , then 4th will be 2nd week of the month
Logic here works as well 4.3 weeks in every month. Take that from the DATEPART(WEEK) on every month but January. Just another way of looking at things. This would also account for months where there is a 5th week
DECLARE #date VARCHAR(10)
SET #date = '7/27/2019'
SELECT CEILING(DATEPART(WEEK,#date)-((DATEPART(MONTH,#date)-1)*4.3333)) 'Week of Month'
Below will only work if you have every week of the month represented in the select list. Else the rank function will not work, but it is a good solution.
SELECT DENSE_RANK() OVER (PARTITION BY MONTH(DATEFIELD)
ORDER BY DATEPART(WEEK,DATEFIELD) ASC) AS WeekofMont
try this one
declare #date datetime = '20210928'
select convert(int,(((cast(datepart(day,#date) as decimal(4,2))/7)-(1.00/7.00))+1.00))
select datepart(week,#date)-datepart(week,dateadd(day,1,eomonth(dateadd(m,-1,#date))))+1
or
select datepart(week,#date)-datepart(week,dateadd(d,-datepart(d,#date)+1,#date))+1
steps:
1,get the first day of month
2,week of year of the date - week of year of the first day of the month
3,+1
2023-1-1 is sunday
SET DATEFIRST 1;
DECLARE #date date = '2023-1-02';
select datepart(week,#date)-datepart(week,dateadd(day,1,eomonth(dateadd(m,-1,#date))))+1
return 2
SET DATEFIRST 7;
DECLARE #date date = '2023-1-02';
select datepart(week,#date)-datepart(week,dateadd(day,1,eomonth(dateadd(m,-1,#date))))+1
return 1
Code is below:
set datefirst 7
declare #dt datetime='29/04/2016 00:00:00'
select (day(#dt)+datepart(WEEKDAY,dateadd(d,-day(#dt),#dt+1)))/7
select #DateCreated, DATEDIFF(WEEK, #DateCreated, GETDATE())