Get calendar week id in sql - sql

i want to get current and current - 7 week id in sql server.
So far i can get that, but for week id under 10 is a problem for me.
DECLARE #CurrentWeek nvarchar(6),#CurrentWeek7 nvarchar(6)
SET #CurrentWeek = CAST(datepart(yy, GETDATE()) AS CHAR(4))+''+CAST(datepart(ww, GETDATE()) AS CHAR(2))
SET #CurrentWeek7 = CAST(datepart(yy, DATEADD(WEEK, -7, GETDATE())) AS CHAR(4)) +''+CAST(datepart(ww, DATEADD(WEEK, -7, GETDATE())) AS CHAR(2))
Problem is that i get for example calendar week id without 0 between year and week number for week number under 10.
20199 instead of 201909. I want this to work also for week number bigger than 10, for example 201911

You can use the RIGHT trick to force a left-sided 0 when the week day is 9 or less.
DECLARE
#CurrentWeek nvarchar(6),
#CurrentWeek7 nvarchar(6)
DECLARE #TodayLastWeek DATE = DATEADD(DAY, -7, GETDATE())
SET #CurrentWeek = CONVERT(VARCHAR(4), DATEPART(YEAR, GETDATE()))
+ RIGHT('0' + CONVERT(VARCHAR(2), DATEPART(WEEK, GETDATE())), 2)
SET #CurrentWeek7 = CONVERT(VARCHAR(4), DATEPART(YEAR, #TodayLastWeek))
+ RIGHT('0' + CONVERT(VARCHAR(2), DATEPART(WEEK, #TodayLastWeek)), 2)
SELECT
CurrentWeek = #CurrentWeek,
CurrentWeek7 = #CurrentWeek7
Result:
CurrentWeek CurrentWeek7
201909 201908
PD: Please check Panagiotis' comment, his solution is faster and simpler.

I am thinking of logic like this:
DECLARE #CurrentWeek nvarchar(6),
#CurrentWeek7 nvarchar(6);
SET #CurrentWeek = dateadd(day,
1 - datepart(weekday, getdate()),
convert(date, getdate())
);
SET #CurrentWeek7 = dateadd(week, -7, #CurrentWeek);
The key idea is that the historical week should be based on the definition of the current week.

DECLARE #CurrentWeek nvarchar(6),#CurrentWeek7 nvarchar(6)
SET #CurrentWeek = CAST(datepart(yy, GETDATE()) AS CHAR(4))* 100+''+CAST(datepart(ww, GETDATE()) AS CHAR(2))
SET #CurrentWeek7 = CAST(datepart(yy, DATEADD(WEEK, -7, GETDATE())) AS CHAR(4))* 100 +''+CAST(datepart(ww, DATEADD(WEEK, -7, GETDATE())) AS CHAR(2))

Related

T-SQL How to get Week Number (ISO) of First Week from all Quarters from GetDate()?

The title says it pritty much.
But to be more precise, I need to get the Week Number of each week first starting in Quarters 1-4 from any given year from GetDate().
Not sure if this is something that's built in or I have to write a function for.
Thanks!
This is simple, but does the trick. You would set #date to any given value. I used getdate().
declare #date datetime = getdate()
declare #year int = datepart(year, #date)
select #year as [year]
,datepart(iso_week, cast('1/1/' + cast(#year as char(4)) as date)) as ISOWeekQ1
,datepart(iso_week, cast('4/1/' + cast(#year as char(4)) as date)) as ISOWeekQ2
,datepart(iso_week, cast('7/1/' + cast(#year as char(4)) as date)) as ISOWeekQ3
,datepart(iso_week, cast('10/1/' + cast(#year as char(4)) as date)) as ISOWeekQ4
For me, this returned:
year ISOWeekQ1 ISOWeekQ2 ISOWeekQ3 ISOWeekQ4
----------- ----------- ----------- ----------- -----------
2017 52 13 26 39
This also works, and doesn't use cast() or risk date conversion errors for different formats of the date (e.g., yyyy/mm/dd):
declare #date datetime = getdate()
set #date = dateadd(day, - datepart(dayofyear, #date) + 1, #date) -- sets date to Jan 1
select datepart(year, #date) [year]
,datepart(iso_week, #date) as ISOWeekQ1
,datepart(iso_week, dateadd(month, 3, #date)) as ISOWeekQ2
,datepart(iso_week, dateadd(month, 6, #date)) as ISOWeekQ3
,datepart(iso_week, dateadd(month, 9, #date)) as ISOWeekQ4
The output of this query is the same as the first.

Pulling a month of rows in SQL Server based on a dynamic day

I have a table in SQL server that looks like this (there are other fields, but there are the only 2 I care about):
-----------------------------------------
| DraftDay (int)| MonthlyFee (money)|
-----------------------------------------
1 18.75
2 15.25
2 15.25
3 15.25
3 28.12
4 15.25
4 3.75
4 18.19
5 12.75
6 13.80
6 14.25
... ...
... ...
What I am trying to do is write a query that will group by DraftDay and sum the MonthlyFee field. Simple enough. But the hard part is, I need to get the date of one month ago, plus one day and pull the days from that day to the current day. For example, if today is 4/3/2014, then I need to pull all days between 3/4/2014 and 4/3/2014. My result set should look like this:
3/4/2014 37.19
3/5/2014 12.75
3/6/2014 28.05
... ...
... ...
4/1/2014 18.75
4/2/2014 30.50
4/3/2014 43.37
I have created this query:
SELECT
CAST(CAST(DATEPART(MONTH, DATEADD(DAY, 1, DATEADD(MONTH, -1, GETDATE()))) AS VARCHAR(2)) + '/' +
CAST(CASE WHEN EftDraftDay>28 THEN 28 ELSE EftDraftDay END AS VARCHAR(2)) + '/' +
CAST(DATEPART(YEAR, DATEADD(DAY, 1, DATEADD(MONTH, -1, GETDATE()))) AS VARCHAR(4)) AS DATETIME) AS DraftDate,
SUM(MonthlyPayment) AS MonthlyPayment FROM dbo.Advertiser
WHERE IsDeleted=0
AND IsPaidInFull=0
AND IsAdvertiserActive=1
AND EftDraftDay>0
AND (CAST(CAST(DATEPART(MONTH, DATEADD(DAY, 1, DATEADD(MONTH, -1, GETDATE()))) AS VARCHAR(2)) + '/' +
CAST(CASE WHEN EftDraftDay>28 THEN 28 ELSE EftDraftDay END AS VARCHAR(2)) + '/' +
CAST(DATEPART(YEAR, DATEADD(DAY, 1, DATEADD(MONTH, -1, GETDATE()))) AS VARCHAR(4)) AS DATETIME)) >=
CAST(CAST(DATEPART(MONTH, DATEADD(DAY, 1, DATEADD(MONTH, -1, GETDATE()))) AS VARCHAR(2)) + '/' +
CAST(DATEPART(DAY, DATEADD(DAY, 1, DATEADD(MONTH, -1, GETDATE()))) AS VARCHAR(2)) + '/' +
CAST(DATEPART(YEAR, DATEADD(DAY, 1, DATEADD(MONTH, -1, GETDATE()))) AS VARCHAR(4)) AS DATETIME)
GROUP BY
CAST(CAST(DATEPART(MONTH, DATEADD(DAY, 1, DATEADD(MONTH, -1, GETDATE()))) AS VARCHAR(2)) + '/' +
CAST(CASE WHEN EftDraftDay>28 THEN 28 ELSE EftDraftDay END AS VARCHAR(2)) + '/' +
CAST(DATEPART(YEAR, DATEADD(DAY, 1, DATEADD(MONTH, -1, GETDATE()))) AS VARCHAR(4)) AS DATETIME)
Because today's date is 4/17/2014, I should be getting results back from 3/18/2014 thru 4/17/2014. The results I'm getting back are only from 3/18/2014 thru 3/28/2014. How can I also add 4/1/2014 thru 4/17/2014 into my result set? I thought about a UNION, but those don't seem to work well with GROUP BY's.
After trying to figure this out and looking at my query, I think I am totally over engineering this. My query looks so complex for such a simple thing. Can anyone please help me out with this?
Try this:
declare #lastmonth date = convert(date,dateadd(day,1,dateadd(month,-1,getdate())))
declare #thismonth date = convert(date,getdate())
select
case
when draftday < datepart(day,#thismonth)
then convert(date, cast(datepart(yyyy,#thismonth) as varchar) + right('00'+cast(datepart(MM,#thismonth) as varchar),2) + right('00'+cast(cast(draftday as varchar) as varchar),2))
else convert(date, cast(datepart(yyyy,#lastmonth) as varchar) + right('00'+cast(datepart(MM,#lastmonth) as varchar),2) + right('00'+cast(cast(draftday as varchar) as varchar),2))
end,
sum(monthlyfee) from tbl
group by draftday
This will treat days before current day as belonging to current month, and others as from last month, and then sum up. Please let me know if this is doing what you expect.
I'd use the Calendar table (http://www.dbdelta.com/calendar-table-and-datetime-functions/), something like this:
declare #d datetime ='20140403'
select c.CalendarDate, sum(#t.MonthlyFee)
from calendar c
left join #t on c.CalendarDay = #t.DraftDay
where CalendarDate between dateadd(month, -1, #d)+1 and #d
group by c.CalendarDate

Finding the list of people who have birthday this week

I am trying to list the people who have birthday this week with this code:
declare #START_DATE date;
set #START_DATE = DATEADD(dd, 1 - DATEPART(dw, getdate()), getdate())
declare #END_DATE date;
set #END_DATE = DATEADD(dd,6, #START_DATE)
set DATEFIRST 1
SELECT #START_DATE as StartDate, Personel.DogumTarihi , #END_DATE as EndDate
,[Adi]
,[Soyadi]
,[BirimAdi]
,[DogumTarihi]
,[MudurlukAdi]
,[Gorevi]
,[CepTelefonu]
,[EvTelefonu]
from Personel
where (
DATEPART(m, Personel.DogumTarihi) = DATEPART(m, #START_DATE)
and DATEPART(DAY, Personel.DogumTarihi) >= DATEPART(DAY, #START_DATE)
and DATEPART(DAY, Personel.DogumTarihi) <= DATEPART(DAY, #END_DATE)
)
OR (
DATEPART(m, Personel.DogumTarihi) = (DATEPART(m, #START_DATE)+ 1)
and DATEPART(DAY, Personel.DogumTarihi) <= DATEPART(DAY, #END_DATE)
)
First I set the start date and calculate the end date according to start date. Then I set Monday as the first day of week.
But everytime I run this, I receive a different Start date. I am quite new to Ms Sql Scripting, I may be doing sth wrong in the declarations but I couldn'd find it. Thanks in advance.
Try this:
SELECT DATEADD(WEEK, DATEDIFF(DAY, 0, GETDATE())/7, 0) FirstDayOfCurrentWeek,
DATEADD(YEAR, DATEDIFF(YEAR, DogumTarihi, GETDATE()), [DogumTarihi]) BirthdayThisYear,
DATEADD(WEEK, 1, DATEADD(WEEK, DATEDIFF(DAY, 0, GETDATE())/7, 0)) FirstDayOfNextWeek
,[Adi]
,[Soyadi]
,[DogumTarihi]
,[BirimAdi]
,[MudurlukAdi]
,[Gorevi]
,[CepTelefonu]
,[EvTelefonu]
FROM Personel
WHERE DATEADD(YEAR, DATEDIFF(YEAR, [DogumTarihi], GETDATE()), [DogumTarihi]) >= DATEADD(WEEK, DATEDIFF(DAY, 0, GETDATE())/7, 0)
AND
DATEADD(YEAR, DATEDIFF(YEAR, [DogumTarihi], GETDATE()), [DogumTarihi]) < DATEADD(WEEK, 1, DATEADD(WEEK, DATEDIFF(DAY, 0, GETDATE())/7, 0))
ok, one more attempt:
where
case when year(#START_DATE) = year(#END_DATE) THEN '1' ELSE CASE WHEN month(#birthdate) = 12 THEN '0' WHEN month(#birthdate) = 1 THEN '1' ELSE '9' END END
+ RIGHT('0' + CONVERT(varchar(2), MONTH(#birthdate)),2)
+ RIGHT('0' + CONVERT(varchar(2), DAY(#birthdate)),2)
between
case when year(#START_DATE) = year(#END_DATE) THEN '1' ELSE '0' END
+ RIGHT('0' + CONVERT(varchar(2), MONTH(#START_DATE)),2)
+ RIGHT('0' + CONVERT(varchar(2), DAY(#START_DATE)),2)
and
'1'
+ RIGHT('0' + CONVERT(varchar(2), MONTH(#END_DATE)),2)
+ RIGHT('0' + CONVERT(varchar(2), DAY(#END_DATE)),2)
sql should let you specify the week directly
DATEPART(ww,GETDATE())
or in oracle: to_char( mydate, 'ww' )
In order to cope with the my problem I revised the code above according to answers:
set DATEFIRST 1
declare #START_DATE date;
set #START_DATE = DATEADD(dd, 1 - DATEPART(dw, getdate()), getdate())
declare #END_DATE date;
set #END_DATE = DATEADD(dd,6, #START_DATE)
SELECT #START_DATE as StartDate,
(case when
(DATEPART(m, #START_DATE) = DATEPART(m, #END_DATE))
then
(case when (DATEPART(DAY, Personel.DogumTarihi) >= DATEPART(DAY, #START_DATE) and DATEPART(DAY, Personel.DogumTarihi) <= DATEPART(DAY, #END_DATE)) then Personel.DogumTarihi else 0 end)
else
(case when DATEPART(m, Personel.DogumTarihi) = DATEPART(m, #START_DATE)
then
(case when (DATEPART(DAY, Personel.DogumTarihi) >= DATEPART(DAY, #START_DATE)) then Personel.DogumTarihi else 0 end)
else
(case when (DATEPART(DAY, Personel.DogumTarihi) <= DATEPART(DAY, #END_DATE)) then Personel.DogumTarihi else 0 end)
end
)
end),
#END_DATE as EndDate, [TCKN]
,[Adi]
,[Soyadi]
,[BirimAdi]
,[DogumTarihi]
,[MudurlukAdi]
,[Gorevi]
,[CepTelefonu]
,[EvTelefonu]
,[VakifTelefonu]
from Personel where
DATEPART(m, #START_DATE) = DATEPART(m, #END_DATE)
OR DATEPART(m, Personel.DogumTarihi) = DATEPART(m, #START_DATE)
OR DATEPART(m, Personel.DogumTarihi) = DATEPART(m, #END_DATE)
Now it is taking the case where "the start and end date of the month are in the same week (like this week)" into account. It looks like it is bringing right results..
Let's have a try:
declare #today datetime
set #today = getdate()
-- erase the hours
set #today = dateadd(hh, -datepart(hh, #today), #today)
-- erase the minutes
set #today = dateadd(mi, -datepart(mi, #today), #today)
-- erase the seconds
set #today = dateadd(ss, -datepart(ss, #today), #today)
-- erase the milliseconds
set #today = dateadd(ms, -datepart(ms, #today), #today)
-- go to start of current week (sunday!)
set #today = dateadd(dd, 1-datepart(dw, #today), #today)
select * from MYTABLE
where DATECOL between
dateadd(yy, datepart(yy, DATECOL) - datepart(yy, #today), #today) and
dateadd(d, 7, dateadd(yy, datepart(yy, DATECOL) - datepart(yy, #today), #today))
Apparently SqlServer 2012 has a DATEFROMPARTS function, in 2005 we will have to use this roundabout way to trim a date.
To select a birthday, I exchange the "today's year" for the record's year. For the end-date of the range I add 7 days to that. Note that you want to search from sunday 0:00 to saturday 23:59.
This will probably still fail if halfway during the week a new year starts and the birthday you want is in the new year.

SQL - Get Numerical Day of Month/Quarter

Using SQL Server 2005:
How can I get the numerical day of the month and day of the quarter in a query?
DECLARE #DATE DATETIME
SET #DATE = GETDATE()
SELECT DATEPART(dy, #DATE) AS DayOfYear
--, <something> AS DayOfQuarter
--, <something> AS DayOfMonth
, DATEPART(dw, #DATE) AS DayOfWeek
Thanks in advance!
DECLARE #DATE DATETIME
SET #DATE = GETDATE()
SELECT DATEPART(dy, #DATE) AS DayOfYear
, DATEDIFF(d, DATEADD(qq, DATEDIFF(qq, 0, #DATE), 0), #DATE) + 1 AS DayOfQuarter
, DAY(#Date) AS DayOfMonth
, DATEPART(dw, #DATE) AS DayOfWeek
As for the day of quarter, this will demande a bit of further investigate on my side. Despite, I guess that for the day of month, this would simply be the date itself:
select DATEPART(D, #DATE)
SELECT
DATEPART(year, '12:10:30.123')
,DATEPART(month, '12:10:30.123')
,DATEPART(day, '12:10:30.123')
,DATEPART(dayofyear, '12:10:30.123')
,DATEPART(weekday, '12:10:30.123');

How do I compare against the current week using SQL Server?

How do I compare an SQL Server date column against the current week?
For instance:
WHERE [Order].SubmittedDate = *THIS WEEK*
You could convert your date to a week number and compare this to the week number from the current date. Likewise, you'll need to compare the year as well, so that you don't get last year's weeks.
WHERE DATEPART(wk, [Order].SubmittedDate) = DATEPART(wk, GETDATE())
AND DATEPART(yy, [Order].SubmittedDate) = DATEPART(yy, GETDATE())
Assuming you are meaning always "this week" and there are no records with Submitted dates in the future, which I imagine could be the case you can do:
WHERE [Order].SubmittedDate >= DATEADD(dd, -(DATEPART(dw, GETDATE()) -1), GETDATE())
If dates do go into the future, the full restriction to this week is:
WHERE [Order].SubmittedDate >= DATEADD(dd, -(DATEPART(dw, GETDATE()) -1), GETDATE())
AND [Order].SubmittedDate < CAST(CONVERT(VARCHAR(10), DATEADD(dd, (8 - DATEPART(dw, GETDATE())), GETDATE()), 120) AS DATETIME)
I'd strongly recommend using a clause based on a start and end date like this, as it will allow efficient index use so should perform better.
Try this:
WHERE [Order].SubmittedDate BETWEEN
DATEADD(d, - DATEPART(dw, GETDATE()) + 1, GETDATE()) AND
DATEADD(d, 7 - DATEPART(dw, GETDATE()) , GETDATE())
Maybe this can run faster, as doesn't needs to be evaluated everytime:
DECLARE #StartDate DATETIME,
#EndDate DATETIME
SELECT #StartDate = DATEADD(d, - DATEPART(dw, GETDATE()) + 1, GETDATE()),
#EndDate = DATEADD(d, 8 - DATEPART(dw, GETDATE()) , GETDATE())
-- // Strip time part, so week starts on Sunday 00:00
SELECT #StartDate = CAST(FLOOR(CAST(#StartDate AS FLOAT)) AS DATETIME),
#EndDate = CAST(FLOOR(CAST(#EndDate AS FLOAT)) AS DATETIME)
...
WHERE [Order].SubmittedDate >= #StartDate AND [Order].SubmittedDate < #EndDate