Good morning,
I have some code, which works perfectly well, but I wanted to know if this could be optimised to run on a while-loop somehow. Basically I want a count per site done on a fortnightly basis, starting from the declared startdate and enddate which is the first fortnight. It would run up until the most recent Sunday. Code below.
DECLARE #Startdate DATE SET #Startdate = '2022-03-14'
DECLARE #enddate DATE
SET #enddate = (select DATEADD(DAY, DATEDIFF(DAY, 13, #Startdate )+13, +13))
Select SiteName
,COUNT ( CASE WHEN CallDate between #Startdate and #enddate THEN CaseID END) as 'Period 1'
,COUNT ( CASE WHEN CallDate between DATEADD(DD,14,#Startdate) and DATEADD(DD, 14 ,#enddate) THEN CaseID END) as 'Period 2'
,COUNT ( CASE WHEN CallDate between DATEADD(DD,28,#Startdate) and DATEADD(DD, 28 ,#enddate) THEN CaseID END) as 'Period 3'
,COUNT ( CASE WHEN CallDate between DATEADD(DD,28,#Startdate) and DATEADD(DD, 28 ,#enddate) THEN CaseID END) as 'Period 4'
FROM [PathwaysDos_LIVE].[dbo].[vwCases]
where SiteTypeID = 5
group by SiteName
Thanks in advance,
Regards, Andrew.
You can use a calendar table. For example, creating it on the fly
DECLARE #Startdate DATE SET #Startdate = '2022-03-14';
with t0(n) as (
select n
from (
values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
) t(n)
), ns as (
select row_number() over(order by t1.n) - 1 n
from t0 t1, t0 t2, t0 t3
), calendar as (
select DATEADD(D, n*14, #Startdate) ds, DATEADD(D, n*14 + 13 ,#Startdate) de
from ns
where DATEADD(D, n*14, #Startdate) < getdate()
)
select SiteName, ds, de
,COUNT ( CASE WHEN CallDate between ds and de THEN CaseID END) as 'Period 1'
,COUNT ( CASE WHEN CallDate between DATEADD(DD, 14, ds) and DATEADD(DD, 14, de) THEN CaseID END) as 'Period 2'
,COUNT ( CASE WHEN CallDate between DATEADD(DD, 28, ds) and DATEADD(DD, 28, de) THEN CaseID END) as 'Period 3'
,COUNT ( CASE WHEN CallDate between DATEADD(DD, 28, ds) and DATEADD(DD, 28, de) THEN CaseID END) as 'Period 4'
from calendar
join [PathwaysDos_LIVE].[dbo].[vwCases]
on SiteTypeID = 5 and CallDate between ds and DATEADD(DD, 28, de)
group by SiteName, ds, de;
Related
The following TSQL returns last 6 month count of data, but if a month does not have records it does not just return 0 as I need it to do, how can I make it do so?
declare #thismonth as Date = DateAdd(d, 1 - DatePart(d, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP);
declare #firstmonth as Date = DateAdd(m, -6, #thismonth);
SELECT YEAR(StartDate) year,
MONTH(StartDate) month,
COUNT(StartDate) EmployeeStartet
FROM
EFP_EmploymentUser
WHERE StartDate BETWEEN #firstmonth AND #thismonth
GROUP BY YEAR(StartDate), MONTH(StartDate)
ORDER BY YEAR(StartDate) DESC, MONTH(StartDate) DESC;
You could do something like this:
declare #lastMonth as Date = DateAdd(d, 1 - DatePart(d, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP);
declare #firstMonth as Date = DateAdd(m, -6, #lastMonth);
WITH months AS (
SELECT #firstMonth AS thisMonth
UNION ALL
SELECT DateAdd(m, 1, thisMonth) AS thisMonth
FROM months
WHERE thisMonth < #lastMonth
),
data AS (
-- your sql here
SELECT YEAR(StartDate) year,
MONTH(StartDate) month,
COUNT(StartDate) EmployeeStartet
FROM
EFP_EmploymentUser
WHERE StartDate BETWEEN #firstmonth AND #thismonth
GROUP BY YEAR(StartDate), MONTH(StartDate)
)
SELECT
YEAR(m.thisMonth) AS year,
MONTH(m.thisMonth) AS month,
ISNULL(d.EmployeeStartet, 0) AS EmployeeStartet
FROM months m
LEFT OUTER JOIN data d
ON
d.year = YEAR(m.thisMonth)
AND d.month = MONTH(m.thisMonth)
ORDER BY m.thisMonth DESC
Left join your data to a tally
declare #thismonth as Date = DateAdd(d, 1 - DatePart(d, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP);
declare #firstmonth as Date = DateAdd(m, -6, #thismonth);
with m as (
select #firstMonth md union
select DateAdd(m, 1, #firstMonth) union
select DateAdd(m, 2, #firstMonth) union
select DateAdd(m, 3, #firstMonth) union
select DateAdd(m, 4, #firstMonth) union
select DateAdd(m, 5, #firstMonth)
),
ym as (
select YEAR(md) y, MONTH(md) m
from m
)
select ym.y, ym.m, COUNT(e.StartDate) EmployeeStartet
from ym
left join EFP_EmploymentUser e
ON (e.StartDate BETWEEN #firstmonth AND #thismonth)
AND ym.y = YEAR(e.StartDate) AND ym.m = MONTH(e.StartDate)
GROUP BY ym.y, ym.m
ORDER BY ym.y DESC, ym.m DESC;
I need to calculate using SQL Query, how many days within a given range fall into each calendar month.
I have given 2 dates, which define a date range; for example 2020-01-01 to 2020-08-03. I need to find how many days in that range fall in to each month i.e. how many fall into July, and how many into August.
In the example given, the expected result is 31 days in July and 3 days in August.
One approach uses a recusive query. Using date artithmetics, we can build the query so it performs one iteration per month rather than one per day, so this should be a rather efficient approach:
with cte as (
select
datefromparts(year(#dt_start), month(#dt_start), 1) month_start,
1 - day(#dt_start) + day(
case when #dt_end > eomonth(#dt_start)
then eomonth(#dt_start)
else #dt_end
end
) as no_days
union all
select
dateadd(month, 1, month_start),
case when #dt_end > dateadd(month, 2, month_start)
then day(eomonth(dateadd(month, 1, month_start)))
else day(#dt_end)
end
from cte
where dateadd(month, 1, month_start) <= #dt_end
)
select * from cte
Demo on DB Fiddle.
If we set the boundaries as follows:
declare #dt_start date = '2020-07-10';
declare #dt_end date = '2020-09-10';
Then the query returns:
month_start | no_days
:---------- | ------:
2020-07-01 | 22
2020-08-01 | 31
2020-09-01 | 10
You can refer this
;with dates(thedate) as (
select dateadd(yy,years.number,0)+days.number
from master..spt_values years
join master..spt_values days
on days.type='p' and days.number < datepart(dy,dateadd(yy,years.number+1,0)-1)
where years.type='p' and years.number between 100 and 150
-- note: 100-150 creates dates in the year range 2000-2050
-- adjust as required
)
select dateadd(m,datediff(m, 0, d.thedate),0) themonth, count(1)
from dates d
where d.thedate between '2020-01-01' and '2020-08-03'
group by datediff(m, 0, d.thedate)
order by themonth;
Please refer the link below where RichardTheKiwi user given a clear example for your scenario.
SQL Server query for total number of days for a month between date ranges
You can do all the work at the month level rather than the day level -- which should be a bit faster. Here is a method using a recursive CTE:
with cte as (
select #startdate as startdate, #enddate as enddate,
datefromparts(year(#startdate), month(#startdate), 1) as month
union all
select startdate, enddate, dateadd(month, 1, month)
from cte
where dateadd(month, 1, month) < #enddate
)
select month,
(case when month <= startdate and dateadd(month, 1, month) >= enddate
then day(enddate) - day(startdate) + 1
when month <= startdate
then day(eomonth(month)) - day(startdate) + 1
when dateadd(month, 1, month) < enddate
then day(eomonth(month))
when dateadd(month, 1, month) >= enddate
then day(enddate)
end)
from cte;
And the db<>fiddle.
The logic is simpler at the day level:
with cte as (
select #startdate as dte, #enddate as enddate
union all
select dateadd(day, 1, dte), enddate
from cte
where dte < enddate
)
select datefromparts(year(dte), month(dte), 1) as yyyymm, count(*)
from cte
group by datefromparts(year(dte), month(dte), 1)
order by yyyymm
option (maxrecursion 0)
Here is a solution with recursive CTE.
declare #startDate date = '2020-07-01'
declare #endDate date = '2020-08-03'
; WITH cte (n, year, month, daycnt)
AS (
SELECT
0
, DATEPART(year, #startDate)
, DATENAME(MONTH, #startDate)
, DATEPART(day, EOMONTH( #startDate ) ) - DATEPART(day, #startDate ) + 1
UNION ALL
SELECT
n + 1
, DATEPART(year, DATEADD(month, n + 1, #startDate) )
, DATENAME(MONTH, DATEADD(month, n + 1, #startDate) )
, IIF(
n = ( DATEPART(month, #endDate) - DATEPART(month, #startDate) ) + ( DATEPART(year, #endDate) - DATEPART(year, #startDate) ) * 12 - 1
, DATEPART(day, #endDate )
, DATEPART(day, EOMONTH( DATEADD(month, n + 1, #startDate) ) )
)
FROM
cte
WHERE
n <= ( DATEPART(month, #endDate) - DATEPART(month, #startDate) ) + ( DATEPART(year, #endDate) - DATEPART(year, #startDate) ) * 12 - 1
)
SELECT *
FROM cte
ORDER BY n
OPTION (maxrecursion 0)
This could be further simplified with a number function but that would also be essentially be a recursive CTE, though it would definitely look cleaner. But it requires defining a function on top of this SELECT statement.
I have two dates from 2019/07/26 and 2019/08/08 from these dates i want result
Year Month ActualDays WorkingDays
------------------------------------
2019 07 06 04
2019 08 08 06
DECLARE #start DATETIME, #end DATETIME
SET #start = '2019-07-26'
SET #end = '2019-08-08'
;WITH c(d) AS
(
SELECT TOP (DATEDIFF(DAY, #start, #end) + 1 )
DATEADD(DAY, ROW_NUMBER() OVER (ORDER BY name)-1, #start)
FROM
sys.all_columns
)
SELECT
YEAR(t.[date]), MONTH(t.[date]), t.[days]
FROM
(SELECT
[date] = DATEADD(MONTH, DATEDIFF(MONTH, 0, d), 0),
[days] = COUNT(*)
FROM
c
GROUP BY
DATEDIFF(MONTH, 0, d)
UNION ALL
SELECT
d, NULL
FROM
c) AS t
WHERE
t.[days] IS NOT NULL
From this I will get days group by month and year I need working days
You can try this-
DECLARE #startdate DATE = '20190701'
, #enddate DATE = '20190716'
DECLARE #temp TABLE(thedate DATE, DoCount INT);
WITH CTE (thedate) AS
(
SELECT #startdate
UNION ALL
SELECT DATEADD(day, 1, thedate)
FROM CTE
WHERE thedate < #enddate
)
INSERT INTO #temp
SELECT thedate,CASE WHEN DATEPART(dw, [thedate]) IN (1,7) THEN 0 ELSE 1 END
FROM CTE
SELECT YEAR(thedate),MONTH(thedate),
COUNT(DoCount) AS ActualDays,
SUM(DoCount) WorkingDays
FROM #temp
GROUP BY YEAR(thedate),
MONTH(thedate)
we need to get week start and end dates for the month output shown as below:
Week# StartDate EndDate
Week 1 2017-03-01 2017-03-04
Week 2 2017-03-05 2017-03-11
Week 3 2017-03-12 2017-03-18
Week 4 2017-03-19 2017-03-25
Week 5 2017-03-26 2017-03-31
This should work:
declare #first_day_of_month date = '20170301'
declare #days_in_month int = datediff(day, #first_day_of_month, dateadd(month, 1, #first_day_of_month))
;with x as (
select datepart(week, dateadd(day, n-1, #first_day_of_month))+1 wk, dateadd(day, n-1, #first_day_of_month) dy
from (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10), (11),(12),(13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23),(24),(25),(26),(27),(28),(29),(30), (31)) as numbers(n)
where n <= #days_in_month
)
select wk - datepart(week, #first_day_of_month) as [Week#], min(dy) as StartDate, max(dy) as EndDate
from x
group by wk
order by wk
If you have Numbers table in the database, you can get rid of the values.
How about this:
Declare #StartDate Date = '2017-03-01'
;With Nums
AS
(
SELECT *
FROM (VALUES (0),(1),(2),(3),(4)) Nums(n)
),
StartDate
AS
(
SELECT #StartDate As StartDate, DatePart(dw,#StartDate) As DayWeekNumber
)
SELECT DATEADD(Week, n, CASE WHEN n = 0 THEN StartDate ELSE DATEADD(Day, DayWeekNumber * -1 + 1, StartDate) END) As StartDate,
CASE WHEN DATEPART(Month, DATEADD(Week, n+1, DATEADD(Day, DayWeekNumber * -1 , StartDate))) = DATEPART(Month, #StartDate)
THEN DATEADD(Week, n+1, DATEADD(Day, DayWeekNumber * -1 , StartDate))
ELSE EOMONTH(#StartDate) END As EndDate
FROM Nums
CROSS JOIN StartDate
Option 1: Non-UDF version
Declare #Date1 date = '2017-03-01'
Declare #Date2 date = '2017-03-31'
Select [Week#]
,StartDate = min(D)
,EndDate = max(D)
From (
Select *,[Week#] = concat('Week ',Dense_Rank() over (Partition By Year(D),Month(D) Order By DatePart(WK,D)))
From (Select Top (DateDiff(DD,#Date1,#Date2)+1) D=DateAdd(DD,-1+Row_Number() Over (Order By Number),#Date1) From master..spt_values ) A1
) A
Group By [Week#],Year(D),Month(D)
Order By 2
Option 2: TFV Version
I'll often use a TVF to create dynamic date/time ranges. A tally/calendar table would do the trick as well, but the UDF offers some dynamic options. You supply the Date Range, DatePart and Increment
Declare #Date1 date = '2017-03-01'
Declare #Date2 date = '2017-03-31'
Select [Week#]
,StartDate = min(RetVal)
,EndDate = max(RetVal)
From (
Select *,[Week#] = concat('Week ',Dense_Rank() over (Partition By Year(RetVal),Month(RetVal) Order By DatePart(WK,RetVal)))
From [dbo].[udf-Range-Date](#Date1,#Date2,'DD',1)
) A
Group By [Week#],Year(RetVal),Month(RetVal)
Order By 2
Both would Return
Week# StartDate EndDate
Week 1 2017-03-01 2017-03-04
Week 2 2017-03-05 2017-03-11
Week 3 2017-03-12 2017-03-18
Week 4 2017-03-19 2017-03-25
Week 5 2017-03-26 2017-03-31
The UDF if interested
CREATE FUNCTION [dbo].[udf-Range-Date] (#R1 datetime,#R2 datetime,#Part varchar(10),#Incr int)
Returns Table
Return (
with cte0(M) As (Select 1+Case #Part When 'YY' then DateDiff(YY,#R1,#R2)/#Incr When 'QQ' then DateDiff(QQ,#R1,#R2)/#Incr When 'MM' then DateDiff(MM,#R1,#R2)/#Incr When 'WK' then DateDiff(WK,#R1,#R2)/#Incr When 'DD' then DateDiff(DD,#R1,#R2)/#Incr When 'HH' then DateDiff(HH,#R1,#R2)/#Incr When 'MI' then DateDiff(MI,#R1,#R2)/#Incr When 'SS' then DateDiff(SS,#R1,#R2)/#Incr End),
cte1(N) As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
cte2(N) As (Select Top (Select M from cte0) Row_Number() over (Order By (Select NULL)) From cte1 a, cte1 b, cte1 c, cte1 d, cte1 e, cte1 f, cte1 g, cte1 h ),
cte3(N,D) As (Select 0,#R1 Union All Select N,Case #Part When 'YY' then DateAdd(YY, N*#Incr, #R1) When 'QQ' then DateAdd(QQ, N*#Incr, #R1) When 'MM' then DateAdd(MM, N*#Incr, #R1) When 'WK' then DateAdd(WK, N*#Incr, #R1) When 'DD' then DateAdd(DD, N*#Incr, #R1) When 'HH' then DateAdd(HH, N*#Incr, #R1) When 'MI' then DateAdd(MI, N*#Incr, #R1) When 'SS' then DateAdd(SS, N*#Incr, #R1) End From cte2 )
Select RetSeq = N+1
,RetVal = D
From cte3,cte0
Where D<=#R2
)
/*
Max 100 million observations -- Date Parts YY QQ MM WK DD HH MI SS
Syntax:
Select * from [dbo].[udf-Range-Date]('2016-10-01','2020-10-01','YY',1)
Select * from [dbo].[udf-Range-Date]('2016-01-01','2017-01-01','MM',1)
*/
For a one-off use, this would work:
rextester: http://rextester.com/WCMZRW61517
declare #FromDate date = '20170301';
with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
, d as (
select DateValue=convert(date,dateadd(day
, row_number() over (order by (select 1)) -1, #FromDate))
from n as deka
cross join n as hecto
)
select
[Week#] = dense_rank() over (
partition by dateadd(month, datediff(month, 0, DateValue) , 0)
order by convert(tinyint,datepart(week,DateValue))
)
, StartDate = min(DateValue)
, EndDate = max(DateValue)
from d
where dateadd(month, datediff(month, 0, DateValue) , 0) = #FromDate
group by
dateadd(month, datediff(month, 0, DateValue) , 0)
, convert(tinyint,datepart(week,DateValue))
If you want to have a calendar table you can reference as needed, something like this would work:
if object_id('dbo.Calendar') is not null drop table dbo.Calendar;
create table dbo.Calendar (
[Date] date not null
, [Year] smallint not null
, [Month] tinyint not null
, MonthStart date not null
, MonthEnd date not null
, [Week] tinyint not null
, MonthWeek tinyint not null
, MonthWeekStart date not null
, MonthWeekEnd date not null
, constraint pk_Calendar primary key clustered (date)
);
declare #FromDate date = '20170101';
declare #ThruDate date = '20171231';
with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
, d as (
select DateValue=convert(date,dateadd(day
, row_number() over (order by (select 1)) -1, #fromdate))
from n as deka
cross join n as hecto
cross join n as kilo /* 2.73 years */
cross join n as [tenK] /* 27.3 years */
--cross join n as [hundredk] /* 273 years */
)
insert into dbo.Calendar
([Date], [Year], [Month],MonthStart, MonthEnd, [Week]
, MonthWeek, MonthWeekStart, MonthWeekEnd)
select top (datediff(day, #FromDate, #ThruDate)+1)
[Date] = DateValue
, [Year] = convert(smallint,datepart(year,DateValue))
, [Month] = convert(tinyint,datepart(month,DateValue))
, MonthStart = dateadd(month, datediff(month, 0, DateValue) , 0)
, MonthEnd = convert(date,dateadd(day,-1
,dateadd(Month,datediff(Month,0,DateValue) +1,0) ) )
, [Week] = convert(tinyint,datepart(week,DateValue))
, MonthWeek = dense_rank() over (
partition by dateadd(month, datediff(month, 0, DateValue) , 0)
order by convert(tinyint,datepart(week,DateValue))
)
, MonthWeekStart = min(DateValue) over (
partition by dateadd(month, datediff(month, 0, DateValue) , 0)
, convert(tinyint,datepart(week,DateValue))
)
, MonthWeekEnd = max(DateValue) over (
partition by dateadd(month, datediff(month, 0, DateValue) , 0)
, convert(tinyint,datepart(week,DateValue))
)
from d
order by DateValue;
select distinct
MonthWeek
, MonthWeekStart
, MonthWeekEnd
from dbo.Calendar
where MonthStart = '20170301'
Calendar and Numbers Tables
Generate a set or sequence without loops - Aaron Bertrand
Creating a Date Table/Dimension in SQL Server 2008 - David Stein
Calendar Tables - Why You Need One - David Stein
Creating a date dimension or calendar table in SQL Server - Aaron Bertrand
TSQL Function to Determine Holidays in SQL Server - Tim Cullen
F_TABLE_DATE - Michael Valentine Jones
I have a query that will return the total number of calls I received each day of last month for a queue. if no calls it will return zero for that day. However when running this report for for December of 2013 the results are blank. It appears to be due to the fact the query is returning the dates with the year of 2014 instead of 2013. How can I adjust the query so the date is 12/01/2013, etc.
DECLARE #pMnth int,#pYr int,#pQueue varchar
SET #pMnth = '12'
SET #pYr = '2013'
SET #pQueue = 'Queue Name'
;
WITH
CTE_Days AS
(
SELECT DATEADD(month, #pMnth, DATEADD(month, -MONTH(GETDATE()), DATEADD(day, -DAY(GETDATE()) + 1, CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME)))) as Dt
UNION ALL
SELECT DATEADD(day, 1, Dt)
FROM CTE_Days
WHERE Dt < DATEADD(day, -1, DATEADD(month, 1, DATEADD(month, #pMnth, DATEADD(month, -MONTH(GETDATE()), DATEADD(day, -DAY(GETDATE()) + 1, CAST(FLOOR(CAST(GETDATE() AS FLOAT)) AS DATETIME))))))
)
SELECT tbl1.Dt,ISNULL(Calls,0) AS Calls
FROM CTE_Days tbl1
LEFT JOIN(
SELECT CAST(clmdate AS Date) AS ClDt,COUNT(*) AS Calls
FROM dbo.tblcalls
WHERE DATEPART(yyyy,clmdate) = #pYr
AND DATEPART(mm,clmdate) = #pMnth
AND clmqueue = #pQueue
GROUP BY CAST(clmdate AS Date)
) tbl2 ON tbl1.Dt = tbl2.ClDt
Not really sure what you're trying to do with all the variables, but if you want the first day of last month:
SELECT DATEADD(month, DATEDIFF(month, 0, GETDATE())-1, 0) -- < SQL 2012
SELECT DATEADD(day,1,EOMONTH(GETDATE(),-2)) -- SQL 2012
Last day of last month:
SELECT DATEADD(day,-1,DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)) -- < SQL 2012
SELECT EOMONTH(GETDATE(),-1) -- SQL 2012
In your code (assuming you're not on 2012):
DECLARE #pMnth int,#pYr int,#pQueue varchar
SET #pMnth = '12'
SET #pYr = '2013'
SET #pQueue = 'Queue Name'
;
WITH
CTE_Days AS
(
SELECT DATEADD(month, DATEDIFF(month, 0, GETDATE())-1, 0) as Dt
UNION ALL
SELECT DATEADD(day, 1, Dt)
FROM CTE_Days
WHERE Dt < DATEADD(day,-1,DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0))
)
SELECT tbl1.Dt,ISNULL(Calls,0) AS Calls
FROM CTE_Days tbl1
LEFT JOIN(
SELECT CAST(clmdate AS Date) AS ClDt,COUNT(*) AS Calls
FROM dbo.tblcalls
WHERE DATEPART(yyyy,clmdate) = #pYr
AND DATEPART(mm,clmdate) = #pMnth
AND clmqueue = #pQueue
GROUP BY CAST(clmdate AS Date)
) tbl2 ON tbl1.Dt = tbl2.ClDt
Update:
To incorporate your variables, I would change the month and year variables to strings, and replace GETDATE() with a date variable:
DECLARE #pMnth CHAR(2)
,#pYr CHAR(4)
,#pQueue VARCHAR(MAX)
,#dt DATE
SET #pMnth = '12'
SET #pYr = '2013'
SET #pQueue = 'Queue Name'
SET #dt = CAST(#pYr+RIGHT('0'+#pMnth,2)+'01' AS DATE)
WITH
CTE_Days AS
(
SELECT DATEADD(month, DATEDIFF(month, 0, #dt)-1, 0) as Dt
UNION ALL
SELECT DATEADD(day, 1, Dt)
FROM CTE_Days
WHERE Dt < DATEADD(day,-1,DATEADD(month, DATEDIFF(month, 0, #dt), 0))
)
SELECT tbl1.Dt,ISNULL(Calls,0) AS Calls
FROM CTE_Days tbl1
LEFT JOIN(
SELECT CAST(clmdate AS Date) AS ClDt,COUNT(*) AS Calls
FROM dbo.tblcalls
WHERE DATEPART(yyyy,clmdate) = #pYr
AND DATEPART(mm,clmdate) = #pMnth
AND clmqueue = #pQueue
GROUP BY CAST(clmdate AS Date)
) tbl2 ON tbl1.Dt = tbl2.ClDt