Select empty weeks in SQL - sql

I am grouping by weeks using DATEPART in SQL. However, I want to include the empty weeks also, not only weeks that include values. I have a script that works perfectly collecting data by weeks, but not the empty weeks. I´ve been trying to use left outer join but my SQL skills are not all that great. I decided to ask you guys.
Here is my script:
select
DatePart(Year, MYTABLE.CREATION_DATE) as DateYear,
DatePart(Month, MYTABLE.CREATION_DATE) as DateMonth,
DatePart(Week, MYTABLE.CREATION_DATE) as DateWeek,
sum(cast(MYTABLE.BASE_TRANSACTION_VALUE as int)) as Value,
min(MYTABLE.CREATION_DATE) as DateT
from MYTABLE
where MYTABLE.SEGMENT2 like '00601'
and MYTABLE.SEGMENT4 like '%'
and MYTABLE.CREATION_DATE > '2012-12-30 12:00:00'
and MYTABLE.CREATION_DATE < '2013-12-30 11:00:00'
group by
DatePart(Year, MYTABLE.CREATION_DATE),
DatePart(Month, MYTABLE.CREATION_DATE),
DatePart(Week, MYTABLE.CREATION_DATE)
order by DateYear, DateMonth, DateWeek
And this is the result of that script.
Could you guys possibly give me an example of a join clause could look like in this case?

[updated 2014-01-09 08:06 UTC]
you can create the dates dynamically (DateRange) and the outer-join them to your select like this:
declare #startdate date;
set #startdate = '2012-12-30';
declare #enddate date;
set #enddate = '2013-12-30'
;with DateRange AS
(
SELECT
DatePart(Year, #startdate) as DateYear,
DatePart(Month, #startdate) as DateMonth,
DatePart(iso_Week, #startdate) as DateWeek,
#startdate as DateValue
UNION ALL
SELECT
DatePart(Year, dateadd(dd,7,DateValue)) as DateYear,
DatePart(Month, dateadd(dd,7,DateValue)) as DateMonth,
DatePart(iso_Week, dateadd(dd,7,DateValue)) as DateWeek,
dateadd(dd,7,DateValue)
FROM DateRange
WHERE dateadd(dd,7,DateValue) <= #enddate
), data as (
select
DatePart(Year, MYTABLE.CREATION_DATE) as DateYear,
DatePart(Month, MYTABLE.CREATION_DATE) as DateMonth,
DatePart(iso_Week, MYTABLE.CREATION_DATE) as DateWeek,
sum(cast(MYTABLE.BASE_TRANSACTION_VALUE as int)) as Value,
min(MYTABLE.CREATION_DATE) as DateT
from MYTABLE
where MYTABLE.SEGMENT2 like '00601'
and MYTABLE.SEGMENT4 like '%'
and MYTABLE.CREATION_DATE > '2012-12-30 12:00:00'
and MYTABLE.CREATION_DATE < '2013-12-30 11:00:00'
group by
DatePart(Year, MYTABLE.CREATION_DATE),
DatePart(Month, MYTABLE.CREATION_DATE),
DatePart(iso_Week, MYTABLE.CREATION_DATE)
)
select
DateRange.DateYear,
DateRange.DateMonth,
DateRange.DateWeek,
data.Value,
data.DateT
from data
right outer join
DateRange
on
data.DateYear = DateRange.DateYear
and data.DateWeek = DateRange.DateWeek
order by
DateRange.DateYear,
DateRange.DateMonth,
DateRange.DateWeek

This should do it. My SQLFiddle is http://www.sqlfiddle.com/#!6/b777f/1/0
declare #WeekTable table(
[WeekDate] datetime
)
declare #startDate datetime,
#EndDate datetime
select #startDate = '1/1/2013',#EndDate = '12/31/2013'
while #startDate<=#EndDate begin
insert into #WeekTable values(#startDate)
set #startDate = #startDate+7
end
select
DatePart(Year, [WeekDate]) as DateYear,
DatePart(Month, [WeekDate]) as DateMonth,
DatePart(Week, [WeekDate]) as DateWeek,
sum(cast(MYTABLE.BASE_TRANSACTION_VALUE as int)) as Value,
min(isnull(MYTABLE.CREATION_DATE,[WeekDate])) as DateT
from
#WeekTable
left outer join
MYTABLE
on
DatePart(Week,MYTABLE.CREATION_DATE) =DatePart(Week, [WeekDate])
and
DatePart(Year,MYTABLE.CREATION_DATE) =DatePart(Year, [WeekDate])
and
MYTABLE.SEGMENT2 like '00601'
and
MYTABLE.SEGMENT4 like '%'
group by
DatePart(Year, [WeekDate]) ,
DatePart(Month, [WeekDate]),
DatePart(Week, [WeekDate])
order by
DateYear, DateMonth, DateWeek

Related

Find the count for last year same week in sql

I am using the below query to find the count from a table based on a date for the last 5-6 weeks as below
BEGIN
SET datefirst 1;
DECLARE #BeginDate datetime= '2016-10-10'
SELECT
count(*) as Total
, datepart(wk, DateCreated) as WeekNumber
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104) as WeekStartDate
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104) as WeekEndDate
FROM TABLESES
WHERE
CONVERT(date,DateCreated) >= DATEADD(DAY, -42, #BeginDate)
AND CONVERT(date,DateCreated) <= DATEADD(DAY, 6, #BeginDate)
GROUP BY datepart(wk, DateCreated)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104)
ORDER BY datepart(wk, DateCreated)
END
This will return a result set like below:
Total WeekNumber WeekStartDate WeekEndDate
51295 36 29.08.2016 04.09.2016
48133 37 05.09.2016 11.09.2016
38991 38 12.09.2016 18.09.2016
38074 39 19.09.2016 25.09.2016
37192 40 26.09.2016 02.10.2016
20835 41 03.10.2016 09.10.2016
23781 42 10.10.2016 16.10.2016
Now I want to add one more column in the end with count for the same week number in last year.
Can I achieve the same in this query itself? Or should I write a totally different query for it? And how can I make this query?
You can use UNION with DATEDIFF to get the same thing for the previous year:
SELECT
count(*) as Total
, datepart(wk, DateCreated) as WeekNumber
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104) as WeekStartDate
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104) as WeekEndDate
FROM TABLESES
WHERE
CONVERT(date,DateCreated) >= DATEADD(DAY, -42, #BeginDate)
AND CONVERT(date,DateCreated) <= DATEADD(DAY, 6, #BeginDate)
GROUP BY datepart(wk, DateCreated)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104)
UNION ALL
SELECT
count(*) as Total
, datepart(wk, DATEDIFF(year,1,DateCreated )) as WeekNumber
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DATEDIFF(year,1,DateCreated ))/7,0),104) as WeekStartDate
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DATEDIFF(year,1,DateCreated ))/7,6),104) as WeekEndDate
FROM TABLESES
WHERE
CONVERT(date,DateCreated) >= DATEADD(DAY, -42, #BeginDate)
AND CONVERT(date,DateCreated) <= DATEADD(DAY, 6, #BeginDate)
GROUP BY datepart(wk, DATEDIFF(year,1,DateCreated ))
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DATEDIFF(year,1,DateCreated ))/7,0),104)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DATEDIFF(year,1,DateCreated ))/7,6),104)
ORDER BY datepart(wk, DATEDIFF(year,1,DateCreated ))
Put your end-result to a temp table and then do something like this:
Be sure to check your date logic with previous year. But hope you get the logic. I havent tested if your "Version" is correct as i have wroted, but i hope you get the picture.
Result with test version
TEST Version:
DECLARE #Weeks1 TABLE(
Total int,
Weeknumber INT,
WeekStartDate nvarchar(50),
WeekEndDate nvarchar(50)
)
DECLARE #Weeks2 TABLE(
Total int,
Weeknumber INT,
WeekStartDate nvarchar(50),
WeekEndDate nvarchar(50)
)
insert into #Weeks1 (Total,Weeknumber,WeekStartDate,Weekenddate)
values ('51295', '36' ,'29.08.2016' ,'04.09.2016'),
('48133', '37' ,'05.09.2016' ,'11.09.2016'),
('38991', '38' ,'12.09.2016' ,'18.09.2016'),
('38074', '39' ,'19.09.2016' ,'25.09.2016'),
('37192', '40' ,'26.09.2016' ,'02.10.2016'),
('20835', '41' ,'03.10.2016' ,'09.10.2016'),
('23781', '42' ,'10.10.2016' ,'16.10.2016')
insert into #Weeks2 (Total,Weeknumber,WeekStartDate,Weekenddate)
values ('324234', '36' ,'29.08.2015' ,'04.09.2015'),
('22333', '37' ,'05.09.2015' ,'11.09.2015'),
('23444', '38' ,'12.09.2015' ,'18.09.2015'),
('566666', '39' ,'19.09.2015' ,'25.09.2015'),
('4345', '40' ,'26.09.2015' ,'02.10.2015'),
('8657', '41' ,'03.10.2015' ,'09.10.2015'),
('8567567', '42' ,'10.10.2015' ,'16.10.2015')
Select a.Total,b.Total as
LastYearTotal,a.Weeknumber,A.WeekStartDate,a.Weekenddate from #Weeks1 a
inner join #Weeks2 b on a.Weeknumber = b.Weeknumber
With your version:
DECLARE #Weeks1 TABLE(
Total int,
Weeknumber INT,
WeekStartDate nvarchar(50),
WeekEndDate nvarchar(50)
)
DECLARE #Weeks2 TABLE(
Total int,
Weeknumber INT,
WeekStartDate nvarchar(50),
WeekEndDate nvarchar(50)
)
BEGIN
SET datefirst 1;
DECLARE #BeginDate datetime= '2016-10-10'
insert into #Weeks1 (Total,Weeknumber,WeekStartDate,Weekenddate)
SELECT
count(*) as Total
, datepart(wk, DateCreated) as WeekNumber
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104) as WeekStartDate
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104) as WeekEndDate
FROM TABLESES
WHERE
CONVERT(date,DateCreated) >= DATEADD(DAY, -42, #BeginDate)
AND CONVERT(date,DateCreated) <= DATEADD(DAY, 6, #BeginDate)
GROUP BY datepart(wk, DateCreated)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104)
ORDER BY datepart(wk, DateCreated)
END
BEGIN
SET datefirst 1;
DECLARE #BeginDate2 datetime= '2015-10-10'
insert into #Weeks2 (Total,Weeknumber,WeekStartDate,Weekenddate)
SELECT
count(*) as Total
, datepart(wk, DateCreated) as WeekNumber
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104) as WeekStartDate
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104) as WeekEndDate
FROM TABLESES
WHERE
CONVERT(date,DateCreated) >= DATEADD(DAY, -42, #BeginDate2)
AND CONVERT(date,DateCreated) <= DATEADD(DAY, 6, #BeginDate2)
GROUP BY datepart(wk, DateCreated)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104)
ORDER BY datepart(wk, DateCreated)
END
Select a.Total,b.Total as
LastYearTotal,a.Weeknumber,A.WeekStartDate,a.Weekenddate from #Weeks1 a
inner join #Weeks2 b on a.Weeknumber = b.Weeknumber
If only weeks matter you can make some date calculations first and have a simpler query
SET datefirst 1;
DECLARE #BeginDate datetime = '2016-10-10'; -- must be start of the week , <= last week -6
declare #nweeks int = 6;
-- this year interval
declare #b1Date datetime = dateadd(week, -#nweeks , #BeginDate); --inclusive
declare #e1Date datetime = dateadd(week, 1 , #BeginDate); -- exclusive
declare #thisYear int = datepart(year, #b1Date);
-- previous year interval
declare #bwk int = datepart(week, #b1Date);
declare #year2 datetime= dateadd(year,datediff(year,0,#b1Date)-1,0);
declare #b2Date datetime = dateadd(week, #bwk-1, #year2);
declare #e2Date datetime = dateadd(week, #bwk + #nweeks, #year2);
-- check it
select #BeginDate, #b1Date, #e1Date, #bwk, #b2Date, #e2Date, datepart(week, #b2Date);
SELECT
count(case datepart(year, DateCreated) when #thisYear then 1 end) as TotalThisYear
, datepart(wk, DateCreated) as WeekNumber
, convert(VARCHAR(20),dateadd(week,datepart(week,DateCreated)-#bwk -1,#b1Date),104) as WeekStartDate
, convert(VARCHAR(20),dateadd(day,7*(datepart(week,DateCreated)-#bwk-1)+6,#b1Date),104) as WeekEndDate
, count(case datepart(year, DateCreated) when #thisYear-1 then 1 end) as TotalPrev
FROM TABLESES
WHERE
CONVERT(date,DateCreated) >= #b1Date AND CONVERT(date,DateCreated) <#e1Date
OR
CONVERT(date,DateCreated) >= #b2Date AND CONVERT(date,DateCreated) <#e2Date
GROUP BY datepart(wk, DateCreated)
ORDER BY datepart(wk, DateCreated)
Yes, you can use your same query but with few modifications. I have used 2 CTE's , one for your query and another for prior year weeks. Then join both on the weeknumber to fetch the needed last column as you can see below.
BEGIN
SET datefirst 1;
DECLARE #BeginDate datetime= '2016-10-10'
;WITH CTE1 as
SELECT
count(*) as Total
, datepart(wk, DateCreated) as WeekNumber
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104) as WeekStartDate
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104) as WeekEndDate
FROM TABLESES
WHERE
CONVERT(date,DateCreated) >= DATEADD(DAY, -42, #BeginDate)
AND CONVERT(date,DateCreated) <= DATEADD(DAY, 6, #BeginDate)
GROUP BY datepart(wk, DateCreated)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,0),104)
, convert(VARCHAR(20),dateadd(week,datediff(day,0,DateCreated )/7,6),104)
,CTE2 as
SELECT count(*) as Total
,datepart(wk, dateadd(year, -1, DateCreated)) as WeekNumber
FROM TABLESES
GROUP BY datepart(wk, dateadd(year, -1, DateCreated))
SELECT CTE1.*, CTE2.Total
FROM CTE1 JOIN CTE2
ON CTE1.WeekNumber = CTE2.WeekNumber
END

Get Year of parameter dates

Is there a way for me to get the year of the months based on the parameter given?
DECLARE #StartDate DATETIME,
#EndDate DATETIME;
SELECT
#StartDate = '2016-02-01',
#EndDate = '2017-03-01';
SELECT
/*is there a way for me to get the year of months based on the parameter dates*/
/*DATEPART(YEAR, DATEADD(YEAR, x.number, #StartDate)) AS Year,*/
DATEPART(MONTH, DATEADD(MONTH, x.number, #StartDate)) AS Month,
DATENAME(MONTH, DATEADD(MONTH, x.number, #StartDate)) AS MonthName
FROM
master.dbo.spt_values x
WHERE
x.type = 'P'
AND x.number <= DATEDIFF(MONTH, #StartDate, #EndDate)
The result of my query....
What I want is that from february to december it'll have a year of 2016 and from january to march it'll have a 2017 year..... based on the parameter that I've given..
Thanks in advance.
Try this:
SELECT YEAR(y.dt) AS Year,
MONTH(y.dt) AS Month,
DATENAME(MONTH, y.dt) AS MonthName
FROM master.dbo.spt_values x
CROSS APPLY (SELECT DATEADD(MONTH, x.number, #StartDate)) AS y(dt)
WHERE x.type = 'P'
AND x.number <= DATEDIFF(MONTH, #StartDate, #EndDate)
Demo here

how to separate date?

In a database
Date
5/29/2013
12/4/2013
12/1/2014
The output will be like this
Year Month date
2013 5 29
2013 12 4
2014 12 1
I tried this code:
select [Date],
right([Date],4) as year ,
left([Date],CHARINDEX('/',[Date])-1) as month ,
substring([Date],3,2) as date
FROM Table1
but it not showed the result properly.
DECLARE #datevar varchar(50) = '10/10/2014'
declare #date datetime = convert(date,#datevar,101)
SELECT datepart(year, #date) AS 'year'
,DATEPART(month, #date) AS 'Month'
,DATEPART(day, #date) AS 'Day'
you can use this also.
Please try:
select
Year(CONVERT(Datetime, [Date])) [Year],
Month(CONVERT(Datetime, [Date])) [Month],
Day(CONVERT(Datetime, [Date])) [Date]
FROM Table1
Try this:
SELECT DATEPART(yyyy,date) AS Year,
DATEPART(mm,date) AS Month,
DATEPART(dd,date) AS Day,
FROM Table1
http://www.w3schools.com/sql/func_datepart.asp
create table #t(id varchar(10))
insert into #t values('5/29/2013'),
('12/4/2013'),
('12/1/2014')
select year(id) as [year],month(id) as [month],day(id) as [day] from #t
As Date is a varchar column, first convert it to DateTime and then do the manipulations as :
SET DATEFORMAT MDY;
select [Date],
cast ([Date] as Datetime),
Year(cast ([Date] as Datetime)) [Year],
Month(cast ([Date] as Datetime)) [Month],
Day(cast ([Date] as Datetime)) [Date]
FROM Table1
DEMO
Please try this too :
select datepart(year,[Date]) [year],
datepart(month,[Date]) [month],
datepart(day,[Date]) [day]
FROM table1
Why are you doing so Just do as written below
SELECT CONVERT(DATE,[date]) ,
YEAR = DATEPART(YEAR , CONVERT(DATETIME, [date])),
MONTH = DATEPART(MONTH , CONVERT(DATETIME, [date])),
DAY = DATEPART(DAY, CONVERT(DATETIME, [date]))
FROM DateTable
You can also use other formats if your data is not in this format

How to get this condition in where clause of Sql

I have a query which gives me the last month's completed data
select * from Tabl
where datepart(month, completed_date) = DATEPART(month, getDate())-1
and datepart(year, completed_date) = datepart(year, getDate())
But it gives me wrong data when the current date is in january
How can I write the condition to return correct data if the current month is January?
SQL Server's DATEADD function will help you here.
select * from Tabl
where datepart(month, completed_date) = DATEPART(month, DATEADD(MM,-1,getDate()))
and datepart(year, completed_date) = datepart(year, DATEADD(MM,-1,getDate()))
The 'MM' used is just a keyword for Month.
Well, try subtracting one month from the date instead:
select *
from Tabl
where month(completed_date) = month(dateadd(month, -1, getdate()) and
year(completed_date) = year(dateadd(month, -1, getdate());
But, if you have an index on completed_date, it is better to put all the operations on getdate() so the expression is "sargable" (that is, an index can be used):
where completed_date >= cast(dateadd(month, -1, getdate() - day(getdate() + 1) as date) and
completed_date < cast(getdate() - day(getdate())
When you subtract the "day of the month" from the date, you get the last day of the previous month.
select * from Tabl
where
datepart(year, completed_date) * 100 + datepart(month, completed_date)
<
datepart(year, getDate()) * 100 + datepart(month, GetDate())

Calendar showing null when date begins in previous year

This is the syntax I am using to create my calendar. The issue that I have is that since the startdate of Week1 is in 2012, startdate is showing as null. Is there a way to have the startdate (or enddate in other instances) populate even when it is in a different year? #Winds Of Change ---
That adds in a start date and end date where previously it was null. But what I am after is for example, I need my date range to run Sat - Wed. So let's take week 53 for 2013. The date range should be 12/28/2013 -- 01/01/14. Is there a way to tinker the calander into displaying in that format?
CREATE TABLE dbo.Calendar (
CalendarYear INT NOT NULL,
CalendarWeek INT NOT NULL,
WeekStartDate VARCHAR(50),
WeekEndDate VARCHAR(50),
CONSTRAINT PK_Calendar PRIMARY KEY (
CalendarYear,
CalendarWeek
)
)
SET DATEFIRST 6
DECLARE #StartDate DATETIME,
#NumOfDays INT
SET #StartDate = '20130101'
SET #NumOfDays = 1000;
WITH calendar
AS (
SELECT TOP (#NumOfDays) dateadd(day, row_number() OVER (
ORDER BY sc1.column_id
) - 1, #StartDate) AS CalendarDate
FROM sys.columns sc1
CROSS JOIN sys.columns sc2
)
INSERT INTO dbo.Calendar (
CalendarYear,
CalendarWeek,
WeekStartDate,
WeekEndDate
)
SELECT DATEPART(year, c.CalendarDate) AS Year,
convert(VARCHAR(100), DATEPART(week, c.CalendarDate)) AS Week, --DATEPART(week, c.CalendarDate) AS Week,
MAX(CASE DATEPART(WEEKDAY, c.CalendarDate)
WHEN 1
THEN convert(VARCHAR(50), c.CalendarDate, 101)
ELSE NULL
END) AS StartDate,
MAX(CASE DATEPART(WEEKDAY, c.CalendarDate)
WHEN 7
THEN convert(VARCHAR(50), c.CalendarDate, 101)
ELSE NULL
END) AS EndDate
FROM calendar c
GROUP BY DATEPART(year, c.CalendarDate),
DATEPART(Week, c.CalendarDate)
ORDER BY Year,
startdate,
convert(VARCHAR(100), DATEPART(week, c.CalendarDate)) --Week
SELECT *
FROM dbo.Calendar
So your problem is is that you're grouping by week and year, but at the beginning/end of the year, the year begins/ends on a different week. So if the first week starts on Wednesday, it's only a 3 day week for that Year.
I've had a small tinker, and I've got it working so that it displays the first/last day of the year as the start/end date of the week, by changing things around. Here is my modified version:
SELECT
DATEPART(year, c.CalendarDate) AS Year,
convert(VARCHAR(100), DATEPART(week, c.CalendarDate)) AS Week, --DATEPART(week, c.CalendarDate) AS Week,
convert(VARCHAR(50), MIN(c.CalendarDate), 101) AS StartDate,
convert(VARCHAR(50), MAX(c.CalendarDate), 101) AS EndDate
FROM
calendar c
GROUP BY
DATEPART(year, c.CalendarDate),
DATEPART(Week, c.CalendarDate)
ORDER BY
Year,
startdate,
convert(VARCHAR(100), DATEPART(week, c.CalendarDate)) --Week
Hope this helps.
EDIT: In response to your comment/edit, have a look at these update statements. Put them after your insert.
EDIT2: Don't use the above insert as well as the updates.
update dbo.Calendar set WeekStartDate = convert(VARCHAR(50), dateadd(day, 1, dateadd(week, -1, cast(WeekEndDate as datetime))), 101)
where WeekStartdate is null
update dbo.Calendar set WeekEndDate = convert(VARCHAR(50), dateadd(day, -1, dateadd(week, 1, WeekStartDate)), 101)
where WeekEndDate is null