need to calculate year,month and day for closing date - sql

I have a table called dates,
Opendate | Closedate
------------+---------------
2015-07-09 | 2016-08-10
I am expecting the output like,
opendate | closedate | diff
------------+---------------+----------------------
2015-07-09 | 2016-08-10 | 1year 1month 1day
2015-07-09 | 2016-03-01 | 8 months 20 days
2015-07-09 | 2015-07-11 | 2 days
But when I run this query:
SELECT opendate,
closedate,
Datediff(year, opendate, closedate) AS years,
Datediff(month, opendate, closedate) AS months,
Datediff(day, opendate, closedate) AS days
FROM dates
It is giving me an output like,
opendate | closedate | years | months | days
------------+---------------+-------+--------+---------
2015-07-09 | 2016-08-10 | 1 | 13 | 397
How can we calculate 1 year 1 month and 1 day

You can use Stacked CTE to find one by one the next year, month and date.
Explanation
Query Below first finds out the DATEDIFF Years of opendate and closedate and checks if the resulting date is greater than closedate. if it is, the actual year difference is DATEDIFF of Y -1. use this new date and fetch the DATEDIFF of months using the same logic and then get the difference in days.
Online Example
Query
WITH D(Opendate,Closedate)AS
(
SELECT CAST('2015-07-09' AS DATE),CAST('2016-08-10' AS DATE)
UNION ALL
SELECT CAST('2015-07-09' AS DATE),CAST('2016-03-01' AS DATE)
UNION ALL
SELECT CAST('2015-07-09' AS DATE),CAST('2015-07-11' AS DATE)
),Y AS
(
SELECT Opendate,Closedate,
CASE
WHEN DATEADD(YEAR,DATEDIFF(YEAR,Opendate,Closedate),Opendate) > Closedate
THEN DATEDIFF(YEAR,Opendate,Closedate) - 1
ELSE DATEDIFF(YEAR,Opendate,Closedate)
END Years
FROM D
), YDate as
(
SELECT Opendate,Closedate,Years,DATEADD(YEAR,Years,Opendate) as Newopendate
FROM Y
),M AS
(
SELECT Opendate,Closedate,Years,Newopendate,
CASE WHEN DATEADD(MONTH,DATEDIFF(MONTH,Newopendate,Closedate),Newopendate) > Closedate
THEN DATEDIFF(MONTH,Newopendate,Closedate) - 1
ELSE DATEDIFF(MONTH,Newopendate,Closedate)
END Months
FROM YDate
)
SELECT Opendate,Closedate,Years,Months,DATEDIFF(Day,DATEADD(MONTH,Months,Newopendate),Closedate) as days
FROM M
Result
Opendate Closedate Years Months days
09-07-2015 00:00 10-08-2016 00:00 1 1 1
09-07-2015 00:00 01-03-2016 00:00 0 7 21
09-07-2015 00:00 11-07-2015 00:00 0 0 2

SELECT opendate,
closedate,
( ( Datediff(year, opendate, closedate) + 'years' )+
(( Datediff(month, opendate, closedate) -
12 * Datediff(year, opendate, closedate)) + 'months') +
( Datediff(day, opendate, closedate) -
( Datediff(year, opendate, closedate) * 365 -
(Datediff(month, opendate, closedate) * 12) )) + 'days'
FROM dates
The logic is you concatenate the years and then deduct the no of months of a year. Similarly deduct for days as well

Create one function as Below
CREATE FUNCTION dbo.GetYearMonthDays
(
#FromDate DATETIME
)
RETURNS NVARCHAR(100)
AS
BEGIN
DECLARE #date datetime, #tmpdate datetime, #years int, #months int, #days int
SELECT #date =#FromDate
SELECT #tmpdate = #date
SELECT #years = DATEDIFF(yy, #tmpdate, GETDATE()) - CASE WHEN (MONTH(#date) > MONTH(GETDATE())) OR (MONTH(#date) = MONTH(GETDATE()) AND DAY(#date) > DAY(GETDATE())) THEN 1 ELSE 0 END
SELECT #tmpdate = DATEADD(yy, #years, #tmpdate)
SELECT #months = DATEDIFF(m, #tmpdate, GETDATE()) - CASE WHEN DAY(#date) > DAY(GETDATE()) THEN 1 ELSE 0 END
SELECT #tmpdate = DATEADD(m, #months, #tmpdate)
SELECT #days = DATEDIFF(d, #tmpdate, GETDATE())
RETURN CONVERT(varchar(10), #years) +' Years ' + CONVERT(varchar(10), #months) + ' Month ' + CONVERT(varchar(10), #days) + ' Days'
END
GO
And use is as below
SELECT opendate,
closedate,dbo.GetYearMonthDays(closedate)
FROM dates
This will give you what you wants.

Related

How to get the week number, start date and end date of Compelete year in SQL Server?

How to get the complete week number, startdate and enddate of complete year.
Note
Week starts from Sunday to Saturday
at the same time week no 1 (ex: 01-01-2020 to 04-01-2020) and last week should be (ex:27-12-2020 to 31-12-2020)
Expecting result
WeekNo WeekStartDate WeekEndDate
===================================
1 2019-01-01 2019-01-05
2 2019-01-06 2019-01-12
3 2019-01-13 2019-01-19
4 2019-01-20 2019-01-26
5 2019-01-27 2019-02-02
6 2019-02-03 2019-02-09
7 2019-02-10 2019-02-16
8 2019-02-17 2019-02-23
9 2019-02-24 2019-03-02
...
...upto end of the year
Actually I tried this one also rextester
If you are interested in 2019 only, then the following code will produce exactly what you are looking for:
DECLARE #weekNum INT = 1;
WITH Weeks AS (
SELECT #weekNum AS WeekNo
UNION ALL
SELECT WeekNo + 1 FROM Weeks WHERE WeekNo + 1 <= 53
)
SELECT WeekNo,
CASE
WHEN WeekStartDate < '2019-01-01' THEN CONVERT(DATE, '2019-01-01')
ELSE CONVERT(DATE, WeekStartDate)
END AS WeekStartDate,
CASE
WHEN WeekEndDate > '2019-12-31' THEN CONVERT(DATE, '2019-12-31')
ELSE CONVERT(DATE, WeekEndDate)
END AS WeekEndDate
FROM (
SELECT WeekNo,
DATEADD(WEEK, WeekNo - 1, '2018-12-30') AS WeekStartDate,
DATEADD(WEEK, WeekNo - 1, '2019-01-05') AS WeekEndDate
FROM Weeks
) a
OUTPUT:
WeekNo WeekStartDate WeekEndDate
1 2019-01-01 2019-01-05
2 2019-01-06 2019-01-12
3 2019-01-13 2019-01-19
4 2019-01-20 2019-01-26
5 2019-01-27 2019-02-02
6 2019-02-03 2019-02-09
7 2019-02-10 2019-02-16
8 2019-02-17 2019-02-23
...
51 2019-12-15 2019-12-21
52 2019-12-22 2019-12-28
53 2019-12-29 2019-12-31
Edit following OP comment about variable start and end dates
Following OP's comment about varying start and end dates, I've revisited the code and made it such that is can work between any two dates:
DECLARE #startDate DATE = CONVERT(DATE, '2019-01-01');
DECLARE #endDate DATE = CONVERT(DATE, '2019-12-31');
DECLARE #weekNum INT = 1;
WITH Weeks AS (
SELECT #weekNum AS WeekNo
UNION ALL
SELECT WeekNo + 1 FROM Weeks WHERE WeekNo + 1 <= DATEDIFF(WEEK, #StartDate, #EndDate) + 1
)
SELECT WeekNo,
CASE
WHEN WeekStartDate < #startDate THEN #startDate
ELSE CONVERT(DATE, WeekStartDate)
END AS WeekStartDate,
CASE
WHEN WeekEndDate > #endDate THEN #endDate
ELSE CONVERT(DATE, WeekEndDate)
END AS WeekEndDate
FROM (
SELECT WeekNo,
DATEADD(WEEK, WeekNo - 1, OffsetStartDate) AS WeekStartDate,
DATEADD(WEEK, WeekNo - 1, OffsetEndDate) AS WeekEndDate
FROM Weeks
INNER JOIN (
SELECT CASE
WHEN DATEPART(WEEKDAY, #startDate) = 1 THEN #startDate
ELSE DATEADD(DAY, 1 - DATEPART(WEEKDAY, #startDate), #startDate)
END AS OffsetStartDate,
CASE
WHEN DATEPART(WEEKDAY, #startDate) = 1 THEN DATEADD(DAY, 6, #startDate)
ELSE DATEADD(DAY, 7 - DATEPART(WEEKDAY, #startDate), #startDate)
END AS OffsetEndDate
) a ON 1 = 1
) a
Simply modify #startDate and #endDate to reflect the desired start and end dates. The format of the string is YYYY-MM-DD.
This will output a variable number of weeks between the two dates, starting and ending on the specified date (creating partial weeks as needed). Hopefully, as per the requirement.
Slightly update on above answer of Martin. You can pass #startDate and #endDate based on your preference.
DECLARE #startDate DATETIME = '2019-01-01'
DECLARE #endDate DATETIME = '2021-01-01'
DECLARE #totalWeeks BIGINT= NULL
SELECT #totalWeeks =datediff(ww,#startdate,#enddate)
DECLARE #weekNum INT = 1;
WITH Weeks AS (
SELECT #weekNum AS WeekNo
UNION ALL
SELECT WeekNo + 1 FROM Weeks WHERE WeekNo + 1 <= #totalWeeks
)
SELECT WeekNo,
CASE
WHEN WeekStartDate < #startDate THEN CONVERT(DATE, '2019-01-01')
ELSE CONVERT(DATE, WeekStartDate)
END AS WeekStartDate,
CASE
WHEN WeekEndDate > #endDate THEN CONVERT(DATE, '2019-12-31')
ELSE CONVERT(DATE, WeekEndDate)
END AS WeekEndDate
FROM (
SELECT WeekNo,
DATEADD(WEEK, WeekNo - 1, #startDate) AS WeekStartDate,
DATEADD(WEEK, WeekNo - 1, #endDate) AS WeekEndDate
FROM Weeks
) a
OPTION (MAXRECURSION 1000);

Calculation of month between 2 dates by year

Need help in understanding on how to Calculate the months by year between 2 dates , able to calculate months between the dates but not by year
ID StartDate Enddate
1 1/1/2016 4/23/2019
2 1/1/2016 4/30/2017
3 1/1/2016 12/31/2018
4 1/1/2017 4/23/2019
5 5/20/2017 11/30/2017
ID StartDate Enddate 2016 2017 2018 2019
1 1/1/2016 4/23/2019 12 12 12 4
2 1/1/2016 4/30/2017 12 4 0 0
3 1/1/2016 12/31/2018 12 12 12 0
4 1/1/2017 4/23/2019 0 12 12 4
5 5/20/2017 11/30/2017 0 7 0 0
Counting intervals like this is tricky in SQL Server. It would be much simpler if the database supported least() and greatest(). Here is a verbose approach:
select id, startdate, enddate,
(case when startdate >= '2017-01-01' or enddate < '2016-01-01' then 0
when startdate < '2016-01-01' and enddate >= '2017-01-01' then 12
when startdate >= '2016-01-01' and enddate >= '2017-01-01' then 13 - month(startdate)
when startdate < '2016-01-01' then month(enddate)
else month(enddate) + 1 - month(startdate)
end) as months_2016,
(case when startdate >= '2018-01-01' or enddate < '2017-01-01' then 0
when startdate < '2017-01-01' and enddate >= '2018-01-01' then 12
when startdate >= '2017-01-01' and enddate >= '2018-01-01' then 13 - month(startdate)
when startdate < '2017-01-01' then month(enddate)
else month(enddate) + 1 - month(startdate)
end) as months_2017,
(case when startdate >= '2019-01-01' or enddate < '2018-01-01' then 0
when startdate < '2018-01-01' and enddate >= '2019-01-01' then 12
when startdate >= '2018-01-01' and enddate >= '2019-01-01' then 13 - month(startdate)
when startdate < '2018-01-01' then month(enddate)
else month(enddate) + 1 - month(startdate)
end) as months_2018
from t;
This basically handles the different conditions on whether the start date is before, during, or after the year in question and the same for the end date.
If you have the years in a table you can do a dynamic pivot like this, it would save you declaring the columns by hand:
CREATE TABLE #Data (ID int, StartDate date, EndDate date);
CREATE TABLE #Year (y int);
SET DATEFORMAT MDY;
insert into #Data
values
(1, '1/1/2016','4/23/2019'),
(2, '1/1/2016','4/30/2017'),
(3, '1/1/2016','12/31/2018'),
(4, '1/1/2017','4/23/2019'),
(5, '5/20/2017','11/30/2017')
;
insert into #Year
values
(2016),
(2017),
(2018),
(2019)
;
DECLARE
#PivotColumnNames AS NVARCHAR(MAX),
#DynamicPivotQuery AS NVARCHAR(MAX);
SELECT
#PivotColumnNames = ISNULL(#PivotColumnNames + ',','') + QUOTENAME(Y)
FROM
#Year;
SELECT
#DynamicPivotQuery =
'SELECT
ID,
StartDate,
EndDate,'
+ #PivotColumnNames +
'FROM
(
select
ID,
StartDate,
EndDate,
Y,
case
when StartDate >= DATEFROMPARTS(Y+1, 1, 1) or EndDate < DATEFROMPARTS(Y, 1, 1) then 0
when StartDate < DATEFROMPARTS(Y, 1, 1) and EndDate >= DATEFROMPARTS(Y+1, 1, 1) then 12
when StartDate >= DATEFROMPARTS(Y, 1, 1) and EndDate >= DATEFROMPARTS(Y+1, 1, 1) then 13 - MONTH(StartDate)
when StartDate < DATEFROMPARTS(Y, 1, 1) then month(EndDate)
else MONTH(EndDate) + 1 - MONTH(StartDate)
end M
from
#Data, #Year
) as SourceTable
PIVOT
(
SUM(M)
FOR Y IN ('
+ #PivotColumnNames +
')
) as PivotTable';
SELECT #DynamicPivotQuery;
EXEC sp_executesql #DynamicPivotQuery;
DROP TABLE #Data, #Year;

Multiple counts and merge columns

I current have a query that grabs the number of parts made per hour between two dates:
DECLARE #StartDate datetime
DECLARE #EndDate datetime
SET #StartDate = '10/10/2018'
SET #EndDate = '11/11/2018'
SELECT
CONVERT(VARCHAR(10), CAST(presstimes AS DATE), 111) AS ForDate,
DATEPART(HOUR, presstimes) AS OnHour,
COUNT(*) AS Totals
FROM
partmasterlist
WHERE
((presstimes >= #StartDate AND presstimes < dateAdd(d, 1, #EndDate))
AND (((presstimes IS NOT NULL))))
GROUP BY
CONVERT(VARCHAR(10), CAST(presstimes AS DATE), 111),
DATEPART(HOUR, presstimes)
ORDER BY
CONVERT(VARCHAR(10), CAST(presstimes AS DATE), 111) ASC;
Output:
Date Hour QTY
---------------------
2018/11/06 11 16
2018/11/06 12 20
2018/11/06 13 29
2018/11/06 14 26
Now I need to add another qty column to count where "trimmingtimes" is set.
I can't figure out how to full join the date and hour columns (e.g. presstimes might have 20qty for Hour 2, but trimmingtimes is NULL for Hour 2);
Input:
ID presstimes trimmingtimes
-----------------------------------------------------------------
1 2018-10-10 01:15:23.000 2018-10-10 01:15:23.000
2 2018-10-10 01:15:23.000 NULL
3 2018-10-10 02:15:23.000 NULL
4 NULL 2018-10-10 03:15:23.000
Output:
Date hour Press QTY T QTY
------------------------------------
10/10/18 1 2 1
10/10/18 2 1 0
10/10/18 3 0 1
I suspect you want something like this:
select convert(date, v.dt) as date,
datepart(hour, v.dt) as hour,
sum(ispress) as num_press,
sum(istrim) as num_trim
from partmasterlist pml cross apply
(values (pml.presstime, 1, 0), (pml.trimmingtime, 0, 1)
) v(dt, ispress, istrim)
group by convert(date, v.dt), datepart(hour, v.dt)
order by convert(date, v.dt), datepart(hour, v.dt);
You can add a where clause for a particular range.

Need days in year month and days

I have a table called Dates
Opendate Closedate
2015-07-09 NULL
2017-01-25 NULL
I want to have the output as
Opendate Workingperiod
2015-07-09 1 years 8 months 20 days
2017-01-25 0 years 1 months 3 days
We need to calculate the difference between opendate and today's date and in year month and days format.
have tried
SELECT Opendate,
CAST(DATEDIFF(month,Opendate,GETDATE())/12 AS VARCHAR(5))+' year '+
CAST(DATEDIFF(month,Opendate,GETDATE())%12 AS VARCHAR(5)) +' month '+
CAST(DATEDIFF(day,DATEADD(month,DATEDIFF(month,Opendate,GETDATE()),Opendate),GETDATE()) AS VARCHAR(5))+' days ' AS Workingperiod
FROM Dates
Output:-
Opendate Workingperiod
2015-07-09 1 year 8 month -8 days
2017-01-25 0 year 2 month -24 days
I am getting days in negative, can someone tell what is wrong in it.
DECLARE #opendate datetime, #date datetime, #years int, #months int, #days int
SELECT #opendate = '2015-07-09'
SELECT #date = #opendate
SELECT #years = DATEDIFF(YYYY, #date, GETDATE()) - CASE WHEN (MONTH(#opendate) > MONTH(GETDATE()))
OR (MONTH(#opendate) = MONTH(GETDATE()) AND DAY(#opendate) > DAY(GETDATE()))
THEN 1 ELSE 0 END
SELECT #date = DATEADD(YYYY, #years, #date)
SELECT #months = DATEDIFF(MONTH, #date, GETDATE()) - CASE WHEN DAY(#opendate) > DAY(GETDATE())
THEN 1 ELSE 0 END
SELECT #date = DATEADD(MONTH, #months, #date)
SELECT #days = DATEDIFF(DAY, #date, GETDATE())
SELECT #years AS 'YEARS', #months AS 'MONTHS', #days AS 'DAYS'
FIRST ENTRY (2015-07-09)
SECOND ENTRY (2017-01-25)

MSSQL - Getting last 6 weeks returns last 8 weeks

I am having a problem with week numbers. The customers week starts on a Tuesday, so ends on a Monday. So I have done:
Set DateFirst 2
When I then use
DateAdd(ww,#WeeksToShow, Date)
It occasionally gives me 8 weeks of information. I think it is because it goes over to the previous year, but I am not sure how to fix it.
If I do:
(DatePart(dy,Date) / 7) - #WeeksToShow
Then it works better, but obviously doesn't work going through to previous years as it just goes to minus figures.
Edit:
My currently SQL (If it helps at all without any data)
Set DateFirst 2
Select
DATEPART(yyyy,SessionDate) as YearNo,
DATEPART(ww,SessionDate) as WeekNo,
DATEADD(DAY, 1 - DATEPART(WEEKDAY, SessionDate + SessionTime), CAST(SessionDate +SessionTime AS DATE)) [WeekStart],
DATEADD(DAY, 7 - DATEPART(WEEKDAY, SessionDate + SessionTime), CAST(SessionDate + SessionTime AS DATE)) [WeekEnd],
DateName(dw,DATEADD(DAY, 7 - DATEPART(WEEKDAY, SessionDate + SessionTime), CAST(SessionDate + SessionTime AS DATE))) as WeekEndName,
Case when #ConsolidateSites = 1 then 0 else SiteNo end as SiteNo,
Case when #ConsolidateSites = 1 then 'All' else CfgSites.Name end as SiteName,
GroupNo,
GroupName,
DeptNo,
DeptName,
SDeptNo,
SDeptName,
PluNo,
PluDescription,
SUM(Qty) as SalesQty,
SUM(Value) as SalesValue
From
PluSalesExtended
Left Join
CfgSites on PluSalesExtended.SiteNo = CfgSites.No
Where
Exists (Select Descendant from DescendantSites where Parent in (#SiteNo) and Descendant = PluSalesExtended.SiteNo)
AND (DATEPART(WW,SessionDate + SessionTime) !=DATEPART(WW,GETDATE()))
AND SessionDate + SessionTime between DATEADD(ww,#NumberOfWeeks * -1,#StartingDate) and #StartingDate
AND TermNo = 0
AND PluEntryType <> 4
Group by
DATEPART(yyyy,SessionDate),
DATEPART(ww,SessionDate),
DATEADD(DAY, 1 - DATEPART(WEEKDAY, SessionDate + SessionTime), CAST(SessionDate +SessionTime AS DATE)),
DATEADD(DAY, 7 - DATEPART(WEEKDAY, SessionDate + SessionTime), CAST(SessionDate + SessionTime AS DATE)),
Case when #ConsolidateSites = 1 then 0 else SiteNo end,
Case when #ConsolidateSites = 1 then 'All' else CfgSites.Name end,
GroupNo,
GroupName,
DeptNo,
DeptName,
SDeptNo,
SDeptName,
PluNo,
PluDescription
order by WeekEnd
There are two issues here, the first is that I suspect you are defining 8 weeks of data as having 8 different values for DATEPART(WEEK, in which case you can replicate the root cause of the issue by looking at what ISO would define as the first week of 2015:
SET DATEFIRST 2;
SELECT Date, Week = DATEPART(WEEK, Date)
FROM (VALUES
('20141229'), ('20141230'), ('20141231'), ('20150101'),
('20150102'), ('20150103'), ('20150104')
) d (Date);
Which gives:
Date Week
-----------------
2014-12-29 52
2014-12-30 53
2014-12-31 53
2015-01-01 1
2015-01-02 1
2015-01-03 1
2015-01-04 1
So although you only have 7 days, you have 3 different week numbers. The problem is that DATEPART(WEEK is quite a simplistic function, and will simply return the number of week boundaries passed since the first day of the year, a better function would be ISO_WEEK since this takes into account year boundaries nicely:
SET DATEFIRST 2;
SELECT Date, Week = DATEPART(ISO_WEEK, Date)
FROM (VALUES
('20141229'), ('20141230'), ('20141231'), ('20150101'),
('20150102'), ('20150103'), ('20150104')
) d (Date);
Which gives:
Date Week
-----------------
2014-12-29 1
2014-12-30 1
2014-12-31 1
2015-01-01 1
2015-01-02 1
2015-01-03 1
2015-01-04 1
The problem is, that this does not take into account that the week starts on Tuesday, since the ISO week runs Monday to Sunday, you could adapt your usage slightly to get the week number of the day before:
SET DATEFIRST 2;
SELECT Date, Week = DATEPART(ISO_WEEK, DATEADD(DAY, -1, Date))
FROM (VALUES
('20141229'), ('20141230'), ('20141231'), ('20150101'),
('20150102'), ('20150103'), ('20150104')
) d (Date);
Which would give:
Date Week
-----------------
2014-12-29 52
2014-12-30 1
2014-12-31 1
2015-01-01 1
2015-01-02 1
2015-01-03 1
2015-01-04 1
So Monday the 29th December is now recognized as the previous week. The problem is that there is no ISO_YEAR built in function, so you will need to define your own. This is a fairly trivial function, even so I almost never create scalar functions because they perform terribly, instead I use an inline table valued function, so for this I would use:
CREATE FUNCTION dbo.ISOYear (#Date DATETIME)
RETURNS TABLE
AS
RETURN
( SELECT IsoYear = DATEPART(YEAR, #Date) +
CASE
-- Special cases: Jan 1-3 may belong to the previous year
WHEN (DATEPART(MONTH, #Date) = 1 AND DATEPART(ISO_WEEK, #Date) > 50) THEN -1
-- Special case: Dec 29-31 may belong to the next year
WHEN (DATEPART(MONTH, #Date) = 12 AND DATEPART(ISO_WEEK, #Date) < 45) THEN 1
ELSE 0
END
);
Which just requires a subquery to be used, but the extra typing is worth it in terms of performance:
SET DATEFIRST 2;
SELECT Date,
Week = DATEPART(ISO_WEEK, DATEADD(DAY, -1, Date)),
Year = (SELECT ISOYear FROM dbo.ISOYear(DATEADD(DAY, -1, Date)))
FROM (VALUES
('20141229'), ('20141230'), ('20141231'), ('20150101'),
('20150102'), ('20150103'), ('20150104')
) d (Date);
Or you can use CROSS APPLY:
SET DATEFIRST 2;
SELECT Date,
Week = DATEPART(ISO_WEEK, DATEADD(DAY, -1, Date)),
Year = y.ISOYear
FROM (VALUES
('20141229'), ('20141230'), ('20141231'), ('20150101'),
('20150102'), ('20150103'), ('20150104')
) d (Date)
CROSS APPLY dbo.ISOYear(d.Date) y;
Which gives:
Date Week Year
---------------------------
2014-12-29 52 2014
2014-12-30 1 2015
2014-12-31 1 2015
2015-01-01 1 2015
2015-01-02 1 2015
2015-01-03 1 2015
2015-01-04 1 2015
Even with this method, by simply getting a date 6 weeks ago you sill still end up with 7 weeks if the date you are using is not a Tuesday, because you will have 5 full weeks, and a part week at the start and a part week at the end, this is the second issue. So you need to make sure your start date is a Tuesday. The following will get you Tuesday of 7 weeks ago:
SELECT CAST(DATEADD(DAY, 1 - DATEPART(WEEKDAY, GETDATE()), DATEADD(WEEK, -6, GETDATE())) AS DATE);
The logic of this is explained better in this answer, the following is the part that will get the start of the week (based on your datefirst settings):
SELECT DATEADD(DAY, 1 - DATEPART(WEEKDAY, GETDATE()), GETDATE());
Then all I have done is substitute the second GETDATE() with DATEADD(WEEK, -6, GETDATE()) so that it is getting the start of the week 6 weeks ago, then there is just a cast to date to remove the time element from it.
This will get you current week + 5 previous weeks starting tuesday:
WHERE dateadd(week, datediff(d, 0, getdate()-1)/7 - 4, 1) <= yourdatecolumn
This will show examples:
DECLARE #wks int = 6 -- Weeks To Show
SELECT
dateadd(week, datediff(d, 0, getdate()-1)/7 - 4, 1) tuesday5weeksago,
dateadd(week, datediff(d, 0, getdate()-1)/7 - 5, 1) tuesday6weeksago,
dateadd(week, datediff(d, 0, getdate()-1)/7 - 6, 1) tuesday7weeksago,
dateadd(week, datediff(d, 0, getdate()-1)/7 - #wks + 1, 1) tuesdaydynamicweeksago
Result:
tuesday5weeksago tuesday6weeksago tuesday7weeksago tuesdaydynamicweeksago
2015-01-27 2015-01-20 2015-01-13 2015-01-20