SQL Server: Count number of records on weekly basis (Week = Thursday to Wednesday) - sql

I need some help in writing an SQL in SQL Server where I need to count number of rows group by weeks. There is a tricky description of week which is following
- For any date before 08/13/2015 the week is of 7 days (i.e. from Thu through Wed)
- For date 08/13/2015 the week is consider a 9 day week (i.e. from Thursday through Friday so its between 08/13/2015 through 08/21/2015)
- For date 08/22/2015 the week is back to 7 days (i.e. Sat through Friday)
Now having said all the above the result I want to see in my report is the following way . NOTE: WE column in the below attached image is the last day of the week for the range.
Sample Result Image

Just write a case statement for the 3 different options. You can find the start day with something like this:
DATEADD(week, DATEDIFF(day, 3,getdate()) / 7, 3) -- Thursdays
DATEADD(week, DATEDIFF(day, 5,getdate()) / 7, 5) -- Saturdays
The numbers 3 and 5 come from the fact that day 0 (=1.1.1900) is Monday.
If you use this a lot, it might be a good idea to write a inline table valued function to return the dates you need.

Related

How to get start & end of same week last year in DB2 using SQL?

I have a weekly report that uses these date parameters:
SELECT *
FROM TABLE
WHERE DATE_FIELD BETWEEN (CURRENT DATE - 8 DAYS) AND (CURRENT DATE - 2 DAYS)
This runs on Mondays to gather the previous week's data (Sun-Sat). What I want now is to run this for the same week of the previous year.
So for example, if the code above runs on Mon 29/06/20, it returns data from Sun 21/06/20 - Sat 27/06/20, i.e. week 26 of 2020. I want it to return data from Sun 23/06/19 - Sat 29/06/19, i.e. week 26 of 2019.
The report runs automatically so I can't just plug in the exact dates each time. I also can't just offset the date parameters to -357 and -367 days, as this gets thrown off by leap years.
I've searched for solutions but they all seem to rely on the DATEADD function, which my DB2 database doesn't recognise.
Does anyone know how I can get the result I'm looking for, please? Any advice would be appreciated! :)
The easiest way to do this is to build a calendar or dates table...(google sql calendar table)
Among the columns you'd have would be
date
year
month
quarter
dayofWeek
startOfWeek
endOfWeek
week_nbr
You can use the week() or week_iso() functions when loading the table, pay attention to the differences and pick the best fit for you.
Such a calendar table makes it easy to compare current period vs prior period.
If you assume that all years have 52 weeks, you can use date arithmetic:
SELECT *
FROM TABLE
WHERE DATE_FIELD BETWEEN (CURRENT DATE - (8 + 364) DAYS) AND (CURRENT DATE - (2 + 364) DAYS)
Because you want the week to start on a Monday, this doesn't have to take leap years into account. It is subtracting exactly 52 weeks -- and leap years do no affect weeks.
This gets more complicated if you have to deal with 52 or 53 week years.
A little bit complicated, but it should work. You may run it as is or test your own date.
SELECT
YEAR_1ST_WEEK_END + WEEKS_TO_ADD * 7 - 6 AS WEEK_START
, YEAR_1ST_WEEK_END + WEEKS_TO_ADD * 7 AS WEEK_END
FROM
(
SELECT
DATE((YEAR(D) - 1)||'-01-01')
+ (7 - DAYOFWEEK(DATE((YEAR(D) - 1)||'-01-01'))) AS YEAR_1ST_WEEK_END
, WEEK(D) - 2 AS WEEKS_TO_ADD
FROM (VALUES DATE('2020-06-29')) T(D)
);
The intermediate column YEAR_1ST_WEEK_END value is the 1-st Sat (end of week) of previous year for given date.
WEEKS_TO_ADD is a number of weeks to add to the YEAR_1ST_WEEK_END date.

How to subtract 13 weeks from a date in PL SQL?

I have a date in sql which will always fall on a Monday and I'm subtracting 13 weeks to get a weekly report. I am trying to get the same 13 week report but for last year's figures as well.
At the moment, I'm using the following:
calendar_date >= TRUNC(sysdate) - 91
which is working fine.
I need the same for last year.
However, when I split this into calendar weeks, there will also be a partially complete week as it will include 1 or 2 days from the previous week. I need only whole weeks.
e.g. the dates that will be returned for last year will be 14-Feb-2015 to 16-May-2015. I need it to start on the Monday and be 16-Feb-2015. This will change each week as I am only interested in complete weeks...
I would do this:
Get the date by substracting 91 days as you're already doing.
Get the number of the day of the week with TO_CHAR(DATE,'d')
Add the number of days until the next monday to the date.
Something like this:
SELECT TO_DATE(TO_DATE('16/05/2015','DD/MM/YYYY'),'DD/MM/YYYY')-91 + MOD(7 - TO_NUMBER(TO_CHAR(TO_DATE(TO_DATE('16/05/2015','DD/MM/YYYY'),'DD/MM/RRRR')-91,'d'))+1,7) d
FROM dual
next_day - returns date of first weekday named by char.
with dates as (select to_date('16/05/2015','DD/MM/YYYY') d from dual)
select
trunc(next_day( trunc(d-91) - interval '1' second,'MONDAY'))
from dates;
I want to get next monday from calculated date. In situation when calculated date is monday i have to move back to previous week ( -1 second).

Pulling a dynamic day range from the previous year in DB2

I have two current SQL queries that I currently use to compare GM% from previous year vs. GM% this year. This is a daily report that I run every morning. The date arithmetic is not very solid and I am trying to find an alternative. Previously I thought that the report would only be for Monday forward, and not including the current day (ie if ran on Tuesday, it would only pull Monday. If ran on Monday it would not pull anything.) Recently that has changed to where when the report is ran on Monday, they want to see Friday-Sunday. What I am considering is setting it to pull the previous 5 day, not including the current day. (Ran on Monday would pull Thur, Fri, Sat, Sun.) The problem is that it has to be a day this year vs same day last year comparison. Anyone who;s tried this knows that it is not easy to get this. Here is my current code for the date arithmetic. I am at a loss guys, I could use some help.
Where DB1.TB1.CLM1>=Current Date-364 days - (DAYOFWEEK(CURRENT DATE) - 2) DAYS
And DB1.TB1.CLM1< Current Date- 364 days
If I hear you right, on Tuesday you would pull stats for Monday. Wed, you pull stats for Mon-Tues. Friday, you pull Mon-Thurs. And for all of these, you need the equivalent day prior year.
The trick is that now on Monday, you need to pull the previous weekend, i.e. Thu-Sun.
You have not defined what to do on Sunday, so I'm leaving that case out.
Try this WHERE statement:
where
( -- do this after Monday
dayofweek(current date) > 2 and
DB1.TB1.CLM1 between ((current date - 364 days) - (dayofweek(current date) - 2) days) and (current_date - 365 days)
)
or
( -- do this on Monday
dayofweek(current date) = 2 and
DB1.TB1.CLM1 between (current date - 368 days) and (current date - 365 days)
)

DateDiff SQL Server Problem

Could some one please explain this to me as I am a touch confused as to why this is happening? Basically what I would like to know is why there is a difference between Sundays date and every other day of this week in weeks from the year 0. If that makes sense!
I tried setting the date first but this had no effect. Surely Monday – Sunday of this week should all have the same difference in weeks from the year zero?
Set Datefirst 1
Select DateName(dw,0) --Monday
Select DateDiff(week, 0, '20091109')--Monday: Difference 5732
Select DateDiff(week, 0, '20091114')--Saturday: Difference 5732
Select DateDiff(week, 0, '20091115')--Sunday: Difference 5733
What makes this even more bizarre is if you take the same two dates and date diff them you get one week for the one and 6 days for the other. Am I missing something here?
Select DateDiff(dd,'20091109','20091115')--6 Days difference
Select DateDiff(ww,'20091109','20091115')--1 Week difference
I am using SQL Server 2005
Sunday is considered the first day of the week in a number of countries.
All the datediff functions do is count the number of date boundarys between the two datetime arguments passed to it. So if a week is defined to start Sunday, then the week boundary is midnight Sunday Morning.
So, From 11:59 Saturday night to 00:01 am Sunday Morning, will be the same datediff(week, x, y) as from 00:01 Sunday to 11:59 PM Saturday Night - 13 days later.
x ------------------------------x ==> 1 week diff
| Su M T W T F S | Su M T W T F S |
| | |
x-x ==> Also 1 week diff
I think the problem you are facing is the boundary dates. Are they inclusive?
Select DateDiff(dd,'20091109','20091115')--6 Days difference
Select DateDiff(dd,'20091109','20091116')--7 Days difference
DateDiff - Returns the number of date and time boundaries crossed between two specified dates. (Books Online Definition)
If you Set Datefirst = 1, Monday is the first day of the week, and the week calculations would use MOD 7 for number of days in the week and /7 for week count, in which sunday would be used as 1, and the others FLOORed to 0.

Access query (SQL) to return records sorted (grouped by) WEEKS

Greetings SQL gurus,
I don't know if you can help me, but I will try. I have several large databases grouped by year (each year in a different database). I want to be able to compare values from a particular week from one year to the next. For example, "show me week 17 of 2008 vs. week 17 of 2002."
I have the following definition of weeks that ideally I would use:
Only 52 weeks each year and 7 days a week (that only takes 364 days),
The first day of the first week starts from January 2nd - which means we do not use January 1st data, and
In leap year, the first day of the first week ALSO starts from the January 2nd plus we skip Feb. 29.
Any ideas?
Thanks in advance.
Best to avoid creating a table because then you have to update and maintain it to get your queries to work.
DatePart('ww',[myDate]) will give you the week number. You may run into some issues though deciding which week belongs to which year - for example if Jan 1 2003 is on Wednesday does the week belong as week 52 in 2002 or week 1 in 2003? Your accounting department will have a day of the week that is your end of week (usually Sat). I usually just pick the year that has the most days in it. DatePart will always count the first week as 1 and in the case of the example above the last week as 53. You may not care that much either way. You can create queries for each year
SELECT DatePart('ww',[myDate]) as WeekNumber,myYearTable.* as WeekNumber
FROM myYearTable
and then join the queries to get your data. You'll loose a couple days at the end of the year if one table has 52 weeks and one has 53 (most will show as 53). Or you can do it by your weekending day - this always gives you Saturday which would push a late week into the following year.
(7-Weekday([myDate]))+[myDate]
then
DatePart('ww',(7-Weekday([myDate]))+[myDate])
Hope that helps
To get the week number
'to get the week number in the year
select datepart( week, datefield)
'to get the week number in the month
select (datepart(dd,datefield) -1 ) / 7 + 1
You don't need to complicate things thinking about leap years, etc. Just compare weeks mon to sun
SInce you havea a specifc defintion of when the week starts that is differnt that the standard used by the db, I think a weeks table is the solution to your problem. For each year create a table that defines the dates contained in each week and the week number. Then by joining to that table as well as the relevant other tables, you can ask for just the data for week 17.
Table structure
Date Week
20090102 1
20090103 1
etc.
I needed to create a query that shows BOTH year AND week numbers, like 2014-52. The year shows correct when you use the Datepart() formula to convert week 53 to week 52 in the previous year, but shows the wrong year for the week that was week 1 previously that should be week 52 now. It show that week as 2015-52 instead of 2014-52.
Furthermore, it sorts the data wrong if you only use only the week number, eg:
2014-1,2014-11,2014-2
To overcome this I created the following query to insert a 0 and also to check for days in week 1 that should still fall under week 52.
ActualWeek: IIf(DatePart("ww",[SomeDate],1,3)=52 And DatePart("ww",[SomeDate])=1, DatePart("yyyy",[SomeDate],1,3)-1,DatePart("yyyy",[SomeDate],1,3)) & "-" & IIf(DatePart("ww",[SomeDate],1,3)<10,"0" & DatePart("ww",[SomeDate],1,3),DatePart("ww",[SomeDate],1,3))