return week number based on date - sql

I am new to T-SQL and needed urgent assistance here.
I am trying to get the week number from a given date.
I understand that there is a build in function for it but the value return is not exactly what I wanted.
For e.g., by using select datepart(wk, '2013-01-07'), it would return me '2'.. but the actually fact is it should return '1' instead of '2'.
Any ideas how to correct this issue?

You can use dy datepart specifier to get dayOfYear number and divide it by 7:
select (datepart(dy, '2013-01-05') - 1) / 7 + 1;
Working DEMO.

Try this
SELECT DATEPART(WEEK,GETDATE())

This depends on hop you define the first week. Does it always start on the same weekday? or does it always start on the first of January? If you want it to always start on the same weekday, then use Set datefirst to tell T-SQL what weekdaty you want to define as the start of the week. If you want it to always start on Jan 1, then just use day of year instead of week, subtract 1, integer divide by 7 and add 1.
declare #dat DateTime = getdate()
Select Select (datepart(dy, #dat)-1) / 7 + 1

Although going from memory, I believe the ISO standard for the first week of the year is the week in the year that the first Thursday of the year is in. This would possibly explain why the built in function gives a result different to that you require.

Related

Improper calculation of a date difference in sql

I need to calculate the difference between DFU.HISTSTART and the last Sunday which is for today is 2/27. It should be dynamic and change every Sunday.
For some reason for this calculation I am getting 3 and should get 4.
,ABS(DATEDIFF(wk,
DATEADD(wk,
DATEDIFF(wk,6,GETDATE()), 0), DFU.HISTSTART))
AS '#WKS of Hist'
Does someone have any ideas?
You have two problems... the first is that you're trying to do the old offset trick with the "6". That works on other date parts but not on week. From the Microsoft Documentation...
For a week (wk, ww) or weekday (dw) datepart, the DATEPART return
value depends on the value set by SET DATEFIRST.
If your DATEFIRST is set to 7 (you can verify by running SELECT ##DATEFIRST;) AND your weeks start on Sundays, the following will work just fine and return a "4".
--===== Setup just the dates in question for a demo
DECLARE #HistStart DATE = '01-30-22'
,#Today DATE = '02-27-22'
;
--===== Demo the "right" way to use "wk".
-- I say "right" way because I don't trust DATEFIRST.
SELECT DATEDIFF(wk,#HistStart,#Today)
;
GO
The second thing is that it's generally a really bad practice to depend on the DATEFIRST setting in this global computing environment. Instead, do the much more universal/bullet-proof method of using Integer math to calculate the number of weeks it's been since date-serial 6, which you correctly identified as a Sunday.
--===== Setup just the dates in question for a demo
DECLARE #HistStart DATE = '01-30-22'
,#Today DATE = '02-27-22'
;
--===== Demo "Bulletproof" Way to calculate the difference in Weeks starting on Sunday
SELECT DATEDIFF(dd,6,#Today)/7 - DATEDIFF(dd,6,#HistStart)/7
;
If you need to calculate week differences in weeks a lot, you might want to turn that into a function so that if the company decides to change the day of the week that is the start of the week, you'll only need to change it in one place. In fact, you might want to have the function read it (the date-serial for the starting day of the week) from a "general settings table".
Another way of doing this:
with last_sunday as (
SELECT
case DAYNAME(current_date())
when 'Sun' then current_date()
when 'Mon'then current_date()-1
when 'Tue'then current_date()-2
when 'Wed'then current_date()-3
when 'Thu'then current_date()-4
when 'Fri'then current_date()-5
when 'Sat'then current_date()-6
else '2020-01-01' end "SUNDAY_DATE"
)
SELECT
DFU.HIST_START_DATE
,LAST_SUNDAY.SUNDAY_DATE
,datediff(week,DFU.HIST_START_DATE,LAST_SUNDAY.SUNDAY_DATE) weeks_diff
FROM DFU
JOIN LAST_SUNDAY
;

How to write a variable within SQL using Dateadd and DateDiff for finding the last TWO days of the previous month

I am trying to write a variable using the dateadd and datediff that shows the last two days of previous month. One variable will be the second to last day of the previous month, the one I am having trouble with. The other will be the last day of the previous month, the one I was able to get. I am using SQL Server.
I've tried looking for it on Stack and I have only seen the last day of the previous month given and NOT the second to last day. I tried learning the dateadd and datediff, (which I still want to do).
This is what I tried so far:
Declare #CurrentMonth as date = '3/1/2019'
Declare #SecLastDayPrevMonth as date = DATEADD(MONTH, DATEDIFF(MONTH, 0, #currentmonth), -2)
Declare #LastDayPrevMonth as date = DATEADD(MONTH, DATEDIFF(MONTH, 0, #currentmonth), -1)
The results I am getting for the seclastdayPrevMonth is 2/28/2019. Instead I would want 2/27/2019
I am also getting 2/28/2019 for lastdayprevmonth which is what I want.
I am writing variables because the current month will change every month, and instead of having to update the other days I need within my query, I want to use variables so I am only updating the current month and everything else is flowing through.
And explanation as to why my dateadd/datediff is wrong and an explanation for why the correct dateadd/datediff is the way it is, will be very helpful
Why not refer to the last day when calculating the second last day? Also, your usage of DATEADD is very weird. The syntax is DATEADD(interval, increment, datetime)
Declare #recmonth as date = '3/1/2019'
Declare #LastDayPrevMonth as date = EOMONTH(DATEADD(MONTH, -1, #RecMonth))
Declare #SecLastDayPrevMonth as date = DATEADD(DAY, -1, #LastDayPrevMonth)
SELECT #SecLastDayPrevMonth, #LastDayPrevMonth
So we can calculate the last day of the previous month by subtracting one month from a date and then calling EOMONTH, which returns the last day of a given month. Then the second last day is just subtracting one day from that.
Yields:
SecLastDayPrevMonth LastDayPrevMonth
------------------- ----------------
2019-02-27 2019-02-28
As to "why", DATEDIFF() takes 3 arguments: datepart (string representation of a specific date part), startdate, enddate (both of which must be convertible to a date-ish object).
0 is essentially SQL's epoch, which, in this case is 1/1/1900. So the difference in months between 0 and 3/1/2019 is (119*12)+2 (+2 because we exclude March, since we aren't calculating a full month) = 1430 months difference.
Then, we are trying to add 2 months to our value. DATEADD() takes 3 arguments: datepart, number, date. But, in the example, you are adding 1430 months to whatever date -2 gets converted to (in this case, I believe it would be 12/30/1899, or 2 days before epoch). So, 1430 months after 12/30/1899 would be 2/30/2019, but February only has 28 days in 2019, so it returns 2/28/2019. In a Leap Year, it probably would return 2/29/2019.
To get your #LastDayPrevMonth and #SecLastDayPrevMonth with only DATEDIFF() and DATEADD(), you just need to change your calculations a little.
First thing you want to do is find the First Day of your Given Month. That can be done with DATEADD(month,DATEDIFF(month,0,#CurrentDate),0). We're essentially using the same thing we used above to calculate the number of months since epoch, but then we are adding those months back to epoch.
Now that we know the First Day of the Given Month, all we have to do is subtract days to get a day from the prior month.
So,
DECLARE #CurrentDate date = '2019-03-15' ; -- Changed it to something in the middle of the month.
DECLARE #FirstDayOfGivenMonth = DATEADD(month,DATEDIFF(month,0,#CurrentDate),0) ; -- 3/1/2019
DECLARE #LastDayOfPrevMonth date = DATEADD(day,-1,#FirstDayOfThisMonth) ; -- 2/28/2019
DECLARE #SecLastDayOfPrevMonth date = DATEADD(day, -2, #FirstDayOfThisMonth) ; -- 2/27/2019
SELECT #LastDayOfPrevMonth AS LDPM, #SecLastDayOfPrevMonth AS SLDPM ;
DECLARE #FourDaysLeftInPrevMonth date = DATEADD(day, -4, #FirstDayOfThisMonth) ; -- 2/25/2019
SELECT #FourDaysLeftInPrevMonth AS FourDaysLeftPrev ;
Granted, since SQL 2012, this can all be accomplished much easier with the EOM() function to get to the last day of a month. But if you only could use the two original functions from your original question, this would be one way to get to your needed values.

Wrong US week number calculation for 1st jan using datepart

SQL server DATEPART function has two options to retrieve week number;
ISO_WEEK and WEEK. I Know the difference between the two, I want to have week numbers based on Sunday start standard as followed in the US; i.e. WEEK. But it doesn't handles partial weeks the way I expected. e.g.
SELECT DATEPART(WEEK,'2015-12-31') --53
SELECT DATEPART(WEEK,'2016-01-01') --1
SELECT DATEPART(WEEK,'2016-01-03') --2
gives two different week numbers for a single week, divided in two years. I wanted to implement something like in the following link for week days.
Week numbers according to US standard
Basically I would like something like this;
SELECT DATEPART(WEEK,'2015-12-31') --1
SELECT DATEPART(WEEK,'2016-01-01') --1
SELECT DATEPART(WEEK,'2016-01-03') --2
EDIT:
Basically I am not good with the division of a single week into two, I have to perform some calculations based on week numbers and the fact that a single week to be divided isn't acceptable. So if above isn't possible.
Is it possible that the week number one would start from 2016-01-03. i.e. what I would in that case would be something like this:
SELECT DATEPART(WEEK,'2015-12-31') --53
SELECT DATEPART(WEEK,'2016-01-01') --53
SELECT DATEPART(WEEK,'2016-01-03') --1
If you want the US numbering, you can do this by taking the WEEK number of the end of the week rather than the date itself.
First ensure that the setting for first day of the week is in fact Sunday on your system. You can verify this by running SELECT ##DATEFIRST; this should return 7 for Sunday. If it doesn't, run SET DATEFIRST 7; first.
SELECT
end_of_week=DATEADD(DAY, 7-(DATEPART(WEEKDAY, '20151231')), '20151231'),
week_day=DATEPART(WEEK, DATEADD(DAY, 7-(DATEPART(WEEKDAY, '20151231')), '20151231'));
Which will return 2016/01/02 - 1.
If you wish generate week number of a date, it will return the week number of the year(input date)
Thus, I think sql server treat '2015-12-31' as the last week of 2015.

Teradata Change format of Week Number

I'm pretty new to SQL so I hope this isn't a dumb question, tried to google but couldn't find anything.
I'm summing sales of departments per week in SQL and am using TD_SYSFNLIB.WEEKNUMBER_OF_YEAR (trans_dt) to get the week number.
I think everything is working except I'd like to change the format of the weeks to the start date of the week, e.g. week 1 = 1/4/15
Also, i'm not sure how to handle the very first of the year week 0 since I think that should be grouped up with week 52 of last year.
The following date math trick should get you Beginning of Week as an actual date without having to join to the SYS_CALENDAR view or using a function:
SELECT CURRENT_DATE - ((CURRENT_DATE - DATE '0001-01-07) MOD 7) AS BOW;
Starting with TD14 there's NEXT_DAY which returns the following weekday, if you subtract 7 days you get the previous day:
next_day(trans_dt - 7, 'sunday')

Getting week number of date in SQL

Is there a way to get the week number of a date with SQL that is database independent?
For example to get the month of a date I use:
SELECT EXTRACT(MONTH FROM :DATE)
But the EXTRACT function doesn't know about weeks in SQL92.
Please pay attention to the fact that I want a solution that is database independent! Do not misinterpret this as a question regarding MS SQL Server.
There doesn't appear to be a single standard SQL function to extract the week number from a date - see here for a comparison of how different SQL dialects can extract different dateparts from date fields.
You can try this.
declare #date datetime
select #date='2013-03-15 00:00:00'
select 'Week No: '+ convert(varchar(10),datepart(wk,#date)) as weekno
Try this one :
SELECT DATENAME(yy,GETDATE())+RIGHT(DATENAME(wk,GETDATE()),2)
To understand DATENAME, please follow this link : sqltutorials.blogspot.be/2007/05/sql-datename.html and for the right, suite101.com/article/sql-functions-leftrightsubstrlengthcharindex-a209089 . There are examples to better understand ;-) It will work on MS and other sql servers normally ;-)
The only db independent solution I see is to get the number of days between today and Jan 1 of curr. year. Then divide it by 7 and round it up. There is 73 days from Jan 1 till today, which gives 10.43 as week number. The ISO week number is 11.
Correction: the number of days between last day of the current week and Jan 1 of curr. year. In this case the ISO week is 10, and 68/7 = 10 (rounded).
The best idea I found is
SELECT ROUND(((DAY(NOW())-1)/7)+1)
select (DATEPART(yyyy , CAST(GETDATE() AS datetime)) * 100 +
DATEPART(ww , CAST(GETDATE() AS datetime))) as week