Calculating monthly sales based on a quarter - sql

I need to calculate the monthly sales for a given quarter.
Here is my code to calculate the previous quarter.
set #quarter = datepart(QQ, getdate()) - 1
if #quarter = 0
begin
set #quarter = 4
set #year = datepart(year, getdate()) -1
end
else set #year = datepart(year, getdate())
Here is my code to calculate the average monthly sales for the entire quarter.
SELECT TOP 5 d.sdealer_name, COUNT(c.icontract_id) / 3 as 'AverageMonthlySales'
FROM dealers d
INNER JOIN contracts c
ON c.sdealer_number = d.sdealer_number
WHERE (d.sdealer_number NOT LIKE '%demo%'
AND d.sdealer_status in ('A', 'R')
AND c.sagent_number = #sagent_number
AND c.sstatus in ('P', 'A', 'C', 'E')
AND c.iproduct_type_id in (4)
AND DATEPART(QQ, c.dtcontract_sale_date) = #quarter
AND DATEPART(year, c.dtcontract_sale_date) = #year)
GROUP BY d.sdealer_name
ORDER BY COUNT(distinct c.icontract_id) desc
How would I calculate the total sales for each month dynamically for the given quarter?

ctrl+h ... just replace quarter datepart with month. is there some reason you haven't tried that?
set #month = datepart(month, getdate()) - 1
if #month = 0
begin
set #month = 12
set #year = datepart(year, getdate()) -1
end
else set #year = datepart(year, getdate())
SELECT TOP 5 d.sdealer_name, COUNT(c.icontract_id) as 'AverageMonthlySales'
FROM dealers d
INNER JOIN contracts c
ON c.sdealer_number = d.sdealer_number
WHERE (d.sdealer_number NOT LIKE '%demo%'
AND d.sdealer_status in ('A', 'R')
AND c.sagent_number = #sagent_number
AND c.sstatus in ('P', 'A', 'C', 'E')
AND c.iproduct_type_id in (4)
AND DATEPART(month, c.dtcontract_sale_date) = #month
AND DATEPART(year, c.dtcontract_sale_date) = #year)
GROUP BY d.sdealer_name
ORDER BY COUNT(distinct c.icontract_id) desc

Related

How to get the First day and last day of the month from given month number and year in SQL Server

I have a month number and year: month 2 and year 2022.
How can I get the first day of that month like 2022-02-01 and last day of month 2022-02-28?
I have seen many posts on getting first and last date of month based on given date or the current date, but I need it based on given month and year.
Thanks in advance
Here is my stored procedure:
ALTER PROCEDURE [dbo].[Rpt_ItemsSales_DayMonthYear_year]-- 2022
#year int = NULL
AS
;WITH months(MonthNumber) AS
(
SELECT 1
UNION ALL
SELECT MonthNumber + 1
FROM months
WHERE MonthNumber < 12
)
SELECT
SalesPos_Dtls.ItemName,
SUM(SalesPos_Dtls.Qty) AS SumQty,
SUM(SalesPos_Dtls.TotalPrice) AS SumTotal,
SalesPos_Dtls.ItemCode,
DATENAME(month, DATEADD(month, m.MonthNumber, 0) - 1) AS MonthName,
m.MonthNumber
FROM
months AS m
LEFT JOIN
SalesPos ON MONTH(SalesPos.StartDate) = m.MonthNumber
AND (status = 'IsPosted')
AND (#year = YEAR(salespos.startdate) OR #year IS NULL)
LEFT JOIN
[dbo].SalesPos_Dtls ON SalesPos.ID = SalesPos_Dtls.OrderId
GROUP BY
m.MonthNumber, dbo.SalesPos_Dtls.ItemName, dbo.SalesPos_Dtls.ItemCode
And this is as far as I got
ALTER PROCEDURE [dbo].[Rpt_ItemsSales_DayMonthYear_year] --2022,1
#year int = NULL,
#month int = NULL
AS
DECLARE #yearr int = #year
DECLARE #monthh int = #month
;WITH months(MonthNumber) AS
(
SELECT 1
UNION ALL
SELECT MonthNumber + 1
FROM months
WHERE MonthNumber < 12
)
SELECT
SalesPos_Dtls.ItemName,
SUM(SalesPos_Dtls.Qty) AS SumQty,
SUM(SalesPos_Dtls.TotalPrice) AS SumTotal,
SalesPos_Dtls.ItemCode,
DATENAME(month, DATEADD(month, m.MonthNumber, 0) - 1) AS MonthName,
m.MonthNumber,
DATEFROMPARTS (#yearr, #monthh, 1) AS MonthStart,
EOMONTH (DATEFROMPARTS (#yearr, #monthh, 1)) AS MonthEnd
FROM
months AS m
LEFT JOIN
SalesPos ON MONTH(SalesPos.StartDate) = m.MonthNumber
AND (status = 'IsPosted')
AND (#year = YEAR(salespos.startdate) OR #year IS NULL)
LEFT JOIN
[dbo].SalesPos_Dtls ON SalesPos.ID = SalesPos_Dtls.OrderId
WHERE
(MONTH(SalesPos.StartDate) = #month OR #month IS NULL)
GROUP BY
m.MonthNumber, dbo.SalesPos_Dtls.ItemName, dbo.SalesPos_Dtls.ItemCode
Screenshot with the sample data:
But I want my data this way :
هوت دوج لارج 3.0000 75.0000
76 January 1 2022-1-01 2022-1-31
هوت دوج ميديم 1.0000 20.0000 77 January 1 2022-1-01 2022-1-31
NULL NULL NULL NULL February 2 2022-2-01 2022-2-28
NULL NULL NULL NULL March 3 NULL 2022-3-01 2022-3-31
SET DATEFIRST 1
DECLARE #Month smallint= 3, #Year smallint = 2022;
/*First and Last day of month as DATE */
select DATEFROMPARTS(#Year, #MONTH, 1)FirstDayOfMonth , EOMONTH(DATEFROMPARTS(#Year, #MONTH, 1)) LastDayofMonth
/*First and Last Weekday of Month */
select DATEPART( dw, DATEFROMPARTS(#Year, #MONTH, 1) ) FirstWeekDayOfMonth , DATEPART(dw, (EOMONTH(DATEFROMPARTS(#Year, #MONTH, 1)))) LastWeekDayofMonth
i dont know if this is the right way to update the question but here is the solution that worked for me.
SELECT DATEADD(month, DATEDIFF(month, 0, #mydate), 0) AS StartOfMonth
SELECT EOMONTH(#mydate) as LastOFMonth
And thanks
edit:
this is the stored procedure. all i wanted is to have 2 columns infront of each item that have the firstday of the month and the last day witch this item was purchased.
i hope this and the stored procedure explain what i mean.
ALTER proc [dbo].[Rpt_ItemsSales_DayMonthYear_year]--Rpt_ItemsSales_DayMonthYear_year 2022
#year int=null
as
;WITH months(MonthNumber) AS
(
SELECT 1
UNION ALL
SELECT MonthNumber+1
FROM months
WHERE MonthNumber < 12
)
select SalesPos_Dtls.ItemName,sum(SalesPos_Dtls.Qty) as SumQty,sum(SalesPos_Dtls.TotalPrice) as SumTotal,SalesPos_Dtls.ItemCode,DateName( month , DateAdd( month , m.MonthNumber , 0 ) - 1 ) as MonthName,
m.MonthNumber, cast(DATEADD(month, DATEDIFF(month, 0, SalesPos.StartDate), 0) as date) AS StartOfMonth,EOMONTH(SalesPos.StartDate) as LastOFMonth
from months as m
left join SalesPos on month(SalesPos.StartDate) = m.MonthNumber and (status = 'IsPosted') and (#year = year(salespos.startdate) or #year is null)
left JOIN [dbo].SalesPos_Dtls on SalesPos.ID=SalesPos_Dtls.OrderId
group by m.MonthNumber,dbo.SalesPos_Dtls.ItemName,dbo.SalesPos_Dtls.ItemCode,cast(DATEADD(month, DATEDIFF(month, 0, SalesPos.StartDate), 0) as date),EOMONTH(SalesPos.StartDate)

Function to exclude Saturdays and Sundays

I created a "Daily Sales Query" that captures all the Total Sales entered from the previous work day which runs Mon-Fri at 8AM.
Question is, if it is Monday today, how can I capture the records from Friday.
so that I can exclude weekends.
Because if it is Monday, the total sales displays 0 which actually makes sense because Sunday is a not a work day. Please assist.
See my current code:
SELECT
CONVERT(VARCHAR, DATEADD(dd, - 1, GETDATE()), 103) AS Date,
'Sales Orders' AS Type,
COUNT(o.SalesOrderID) AS Orders,
SUM(d.QtyOrdered) AS Chairs,
ISNULL(ROUND(SUM(d.ExtendedPrice), 2), 0) AS [Total Ex GST]
FROM
dbo.SalesOrder o
LEFT OUTER JOIN
dbo.SalesOrderDetails d ON o.SalesOrderID = d.SalesOrderID
WHERE
(o.EntryDate >= CONVERT(CHAR(8), DATEADD(dd, - 1, GETDATE()), 112))
AND (o.EntryDate < CONVERT(CHAR(8), GETDATE(), 112))
AND (o.CustomerID <> 187);
You can use datediff(dd,0,getdate()) % 7 = 0 to determine if the current date is a Monday regardless of any other server settings (this is because the zero date in SQL Server is 1900-01-01 which happens to be a Monday).
declare #start date;
declare #finish date;
set #start = dateadd(dd, case when datediff(dd,0,getdate()) % 7 = 0 then -3 else -1 end, getdate());
set #finish = dateadd(dd,1,#start);
select
#start, datename(weekday,#start)
, #finish, datename(weekday,#finish)
, datename(weekday,getdate())
;
So in your query I would use:
declare #start date;
declare #finish date;
set #start = dateadd(dd, case when datediff(dd,0,getdate()) % 7 = 0 then -3 else -1 end, getdate());
set #finish = dateadd(dd,1,#start);
SELECT
CONVERT(VARCHAR, #start, 103) AS Date,
'Sales Orders' AS Type,
COUNT(o.SalesOrderID) AS Orders,
SUM(d.QtyOrdered) AS Chairs,
ISNULL(ROUND(SUM(d.ExtendedPrice), 2), 0) AS [Total Ex GST]
FROM
dbo.SalesOrder o
LEFT OUTER JOIN
dbo.SalesOrderDetails d ON o.SalesOrderID = d.SalesOrderID
WHERE
o.EntryDate >= #start
AND o.EntryDate < #finish
AND o.CustomerID <> 187
;
If you use a case statement to determine how many days in the past you need to go e.g.
dateadd(dd, case when datepart(weekday,getdate()) = 1 then -3 else -1 end, getdate()) -- StartDate
dateadd(dd, case when datepart(weekday,getdate()) = 1 then -2 else 0 end, getdate()) -- EndDate
so your code would look like
SELECT
CONVERT(VARCHAR, dateadd(dd, case when datepart(weekday,getdate()) = 1 then -3 else -1 end, getdate()), 103) AS Date,
'Sales Orders' AS Type,
COUNT(o.SalesOrderID) AS Orders,
SUM(d.QtyOrdered) AS Chairs,
ISNULL(ROUND(SUM(d.ExtendedPrice), 2), 0) AS [Total Ex GST]
FROM
dbo.SalesOrder o
LEFT OUTER JOIN
dbo.SalesOrderDetails d ON o.SalesOrderID = d.SalesOrderID
WHERE
(o.EntryDate >= CONVERT(CHAR(8), dateadd(dd, case when datepart(weekday,getdate()) = 1 then -3 else -1 end, getdate()), 112))
AND (o.EntryDate < CONVERT(CHAR(8), dateadd(dd, case when datepart(weekday,getdate()) = 1 then -2 else 0 end, getdate()), 112))
AND (o.CustomerID <> 187);
PS: Do confirm that weekday 1 is Monday on your server.

TSQL calculating from combined queries

I currently have six queries in which I take the results and use a spreadsheet to calculate two different final percentages. I believe that it can be done in a single query, and without a spreadsheet, but I am not knowledgeable enough in SQL to figure it out. I am hoping for some direction from the amazing SQL Gods here on SO.
We have several locations, and calculate a Past Due % and a Past Due Fallout %, per location, based on the average of two other percentages:
Past Due Dollars ÷ Projected Dollars = Past Due Float %
Past Due Units ÷ Total Active Units = Past Due Unit %
( Past Due Unit % + Past Due Dollar % ) / 2 = Past Due %
Fallout uses the same calculations, but looks at what the amounts will be tomorrow.
SOLVED: I spent time learning about sub-queries, and joined them by the STID. Thanks for all who assisted and helped guide me in the
correct direction.
Here is my final code:
SET DATEFIRST 1;
DECLARE #Today date = dbo.getdateparam(92,999);
DECLARE #TodayNum int = DATEPART(dw, #Today);
DECLARE #Saturday date = DATEADD(DAY, (6-#TodayNum)%7, #Today);
DECLARE #PrevSat date = DATEADD(DAY, -7, #Saturday);
Select store.STID As Store,
Proj.ProjRent As Projected,
PDRent.PastDueDollars As PDRent,
UOR.Units As UOR,
PDUnits.UnitsPD As PDUnits,
(PDRent.PastDueDollars / Proj.ProjRent) * 100 As FloatPerc,
(Cast(PDUnits.UnitsPD As Decimal) / Cast(UOR.Units As Decimal)) *
100 As UnitPerc,
Cast(Round((((PDRent.PastDueDollars / Proj.ProjRent) * 100) +
((Cast(PDUnits.UnitsPD As Decimal(18,4)) / Cast(UOR.Units As Decimal(18,4))) *
100)) / 2, 2) As Decimal(18,2)) As PDPerc,
Reds.RedsPD As PDReds,
Round(Cast(Reds.RedsPD As Float) / Cast(UOR.Units As Float) * 100,
2) As RedsPerc
From
-- Stores
(Select Distinct Stores.STID,
Stores.StoreName,
Stores.EMail,
Stores.ManagersName
From Stores
Where Stores.STID Not In (7, 999)) As store
-- Projected Rent
Left Join (Select CashProj.STID,
Sum(CashProj.ProjectedRental) As ProjRent
From CashProj
Where CashProj.ProjectionDate Between DateAdd(mm, DateDiff(mm, 0, #Today),
0) And DateAdd(mm, DateDiff(mm, 0, #Today) + 1, 0)
Group By CashProj.STID) As Proj On store.STID = Proj.STID
-- Past Due Float
Left Join (Select Agreemnt.STID As STID,
Sum(DateDiff(d, Agreemnt.DueDate, (Case DatePart(dw, #Today)
When '1' Then DateAdd(DAY, -7, DateAdd(DAY, (6 - DatePart(dw,
#Today)) % 7, #Today)) When '6' Then #Today
Else DateAdd(DAY, (6 - DatePart(dw, #Today)) % 7, #Today)
End)) * Round(Agreemnt.WeeklyRate / 7, 2)) As PastDueDollars,
DatePart(dw, #Today) As TodayNum,
DateAdd(DAY, -7, DateAdd(DAY, (6 - DatePart(dw, #Today)) % 7,
#Today)) As PrevSat,
DateAdd(DAY, (6 - DatePart(dw, #Today)) % 7, #Today) As Saturday
From Agreemnt
Where Agreemnt.AStatID = 1 And Agreemnt.DueDate < (Case DatePart(dw,
#Today)
When '1' Then DateAdd(DAY, -7, DateAdd(DAY, (6 - DatePart(dw,
#Today)) % 7, #Today)) When '6' Then #Today
Else DateAdd(DAY, (6 - DatePart(dw, #Today)) % 7, #Today)
End) And Agreemnt.RentToRent = 0
Group By Agreemnt.STID) As PDRent On store.STID = PDRent.STID
-- Units On Rent
Left Join (Select Invntry.STID,
Cast(Count(Invntry.StockNumber) As Int) As Units
From Invntry
Inner Join AgreHist On Invntry.InvID = AgreHist.InvID And
Invntry.STID = AgreHist.STID
Inner Join Agreemnt On Agreemnt.STID = AgreHist.STID And
Agreemnt.AgreeID = AgreHist.AgreeID And Agreemnt.AStatID =
AgreHist.AStatID
Where Invntry.InvStatID = 11 And Invntry.DisposalDate Is Null And
Agreemnt.AStatID = 1
Group By Invntry.STID) As UOR On store.STID = UOR.STID
-- Past Due Units
Left Join (Select Invntry.STID,
Cast(Count(Invntry.StockNumber) As Int) As UnitsPD
From Invntry
Inner Join AgreHist On Invntry.InvID = AgreHist.InvID And
Invntry.STID = AgreHist.STID
Inner Join Agreemnt On Agreemnt.STID = AgreHist.STID And
Agreemnt.AgreeID = AgreHist.AgreeID And AgreHist.AStatID =
Agreemnt.AStatID
Where Invntry.InvStatID = 11 And Invntry.DisposalDate Is Null And
Agreemnt.AStatID = 1 And Agreemnt.DueDate < (Case #TodayNum When '1' Then #PrevSat When '6' Then #Today Else #Saturday End) And Agreemnt.RentToRent = 0
Group By Invntry.STID) As PDUnits On store.STID = PDUnits.STID
-- Reds
Left Join (Select Invntry.STID,
Count(Invntry.StockNumber) As RedsPD
From Invntry
Inner Join AgreHist On Invntry.InvID = AgreHist.InvID And
Invntry.STID = AgreHist.STID
Inner Join Agreemnt On Agreemnt.STID = AgreHist.STID And
Agreemnt.AgreeID = AgreHist.AgreeID And Agreemnt.AStatID =
AgreHist.AStatID
Where Invntry.InvStatID = 11 And Invntry.DisposalDate Is Null And
Agreemnt.AStatID = 1 And Agreemnt.DueDate < DateAdd(day, -15, Case
Cast(DatePart(dw, #Today) As Int)
When '1' Then Cast(DateAdd(DAY, -7, DateAdd(DAY, (6 - DatePart(dw,
#Today)) % 7, #Today)) As Date)
When '6' Then Cast(#Today As Date)
Else Cast(DateAdd(DAY, (6 - DatePart(dw, #Today)) % 7, #Today) As
Date) End) And Agreemnt.RentToRent = 0
Group By Invntry.STID) As Reds On store.STID = Reds.STID
Order By Store
You can't use variables like that and you can't do this in one aggregate query because it's going to create a massive Cartesian product and give you incorrect results.
You could use CTE's or subqueries for each query you have listed and then join them together on the STID and apply your formulas.
example...
/* declare all variables here */
DECLARE #dayNum INT;
SET #dayNum = datepart(dw, getdate());
with PastDueDollars as (
select ... from ... group by STID
), ProjectedDollers as (
select ... from ... group by STID
), PastDueUnits as (
select ... from ... group by STID
), preFinal as (
select
PastDueDollarRatio = pdd.PastDueDollars / pd.ProjRent,
PastDueUnitRatio = pdu.UnitsPD / tau.TotalActiveUnits
/* add the other calculations */
from
PastDueDollars pdd
inner join ProjectedDollers pd on pdd.STID = pd.STID
inner join PastDueUnits pdu on pdu.STID = pd.STID
/* join more CTEs */
)
select
f.*,
PastDueRatio = (f.PastDueDollarRatio + f.PastDueUnitRatio) / 2
/* and so on for the other calculations of calculations... */
from
preFinal f
You never set the variables to any real value, the you proceed to select the useless variable in a irrelevant SELECT statement.
in the following line
Set #pdD = Sum( Case When a.DueDate < GetDate() Then DateDiff(d,a.DueDate,#runDate) * (a.WeeklyRate/7) )
You are not stating where s.DueDate comes from. It wont even compile.
In this SELECT the table is completely irrelevant
Select a.STID as STID,
#pdU As PastDueUnits,
#activeU As ActiveUnits,
#pdD As PastDueDollars,
#projRent As ProjRent,
#pdP As PastDuePerc,
#foU As FalloutUnits,
#foD As FalloutDollars,
#foP As FalloutPerc
FROM Agreemnt a INNER JOIN CashProj on a.STID = CashProj.STID JOIN Invntry i ON a.STID = i.STID JOIN AgreHist h On i.InvID = h.InvID And i.STID = h.STID INNER JOIN Agreemnt a On a.STID = h.STID AND a.AgreeID = h.AgreeID AND a.AStatID = h.AStatID
WHERE a.RentToRent = 0 AND i.InvStatID = 11 AND i.DisposalDate IS NULL AND a.AStatID = 1 AND a.DueDate < DateAdd(d, #runDate, GetDate())
GROUP BY a.STID
ORDER BY a.STID
This is an example to how you should set the values before you try to do calculations with the variables.
DECLARE #dayNum INT;
SET #dayNum = datepart(dw, getdate());
Select Invntry.STID,
#foU = COUNT(Invntry.StockNumber)
From Invntry
Inner Join AgreHist On Invntry.InvID = AgreHist.InvID And
Invntry.STID = AgreHist.STID
Inner Join Agreemnt On Agreemnt.STID = AgreHist.STID And Agreemnt.AgreeID =
AgreHist.AgreeID And Agreemnt.AStatID = AgreHist.AStatID
Where Invntry.InvStatID = 11 And Invntry.DisposalDate Is Null And
Agreemnt.AStatID = 1 And Agreemnt.DueDate < DateAdd(d, Case #dayNum When '1' Then -2 When '2' Then 1 When '3' Then 1 When '4' Then 1
When '5' Then 1 When '6' Then 0 When '7' Then -1 End, GetDate()) And Agreemnt.RentToRent = 0
Group By Invntry.STID
My problem was a lack of knowledge and understanding of SQL, which I'm improving on. Here is what I ended up with that gave me the result I desired, whether the most efficient or not.
SET DATEFIRST 1;
DECLARE #Today date = dbo.getdateparam(92,999);
DECLARE #TodayNum int = DATEPART(dw, #Today);
DECLARE #Saturday date = DATEADD(DAY, (6-#TodayNum)%7, #Today);
DECLARE #PrevSat date = DATEADD(DAY, -7, #Saturday);
Select store.STID As Store,
Proj.ProjRent As Projected,
PDRent.PastDueDollars As PDRent,
UOR.Units As UOR,
PDUnits.UnitsPD As PDUnits,
(PDRent.PastDueDollars / Proj.ProjRent) * 100 As FloatPerc,
(Cast(PDUnits.UnitsPD As Decimal) / Cast(UOR.Units As Decimal)) * 100 As UnitPerc,
Cast(Round((((PDRent.PastDueDollars / Proj.ProjRent) * 100) + ((Cast(PDUnits.UnitsPD As Decimal(18,4)) / Cast(UOR.Units As Decimal(18,4))) * 100)) / 2, 2) As Decimal(18,2)) As PDPerc,
Reds.RedsPD As PDReds,
Round(Cast(Reds.RedsPD As Float) / Cast(UOR.Units As Float) * 100,2) As RedsPerc
From
-- Stores
(Select Distinct Stores.STID,
Stores.StoreName,
Stores.EMail,
Stores.ManagersName
From Stores
Where Stores.STID Not In (7, 999)) As store
-- Projected Rent
Left Join (Select CashProj.STID,
Sum(CashProj.ProjectedRental) As ProjRent
From CashProj
Where CashProj.ProjectionDate Between DateAdd(mm, DateDiff(mm, 0, #Today),0) And DateAdd(mm, DateDiff(mm, 0, #Today) + 1, 0)
Group By CashProj.STID) As Proj On store.STID = Proj.STID
-- Past Due Float
Left Join (Select Agreemnt.STID As STID,
Sum(DateDiff(d, Agreemnt.DueDate, (Case DatePart(dw, #Today) When '1' Then DateAdd(DAY, -7, DateAdd(DAY, (6 - DatePart(dw, #Today)) % 7, #Today)) When '6' Then #Today
Else DateAdd(DAY, (6 - DatePart(dw, #Today)) % 7, #Today) End)) * Round(Agreemnt.WeeklyRate / 7, 2)) As PastDueDollars,
DatePart(dw, #Today) As TodayNum,
DateAdd(DAY, -7, DateAdd(DAY, (6 - DatePart(dw, #Today)) % 7,
#Today)) As PrevSat,
DateAdd(DAY, (6 - DatePart(dw, #Today)) % 7, #Today) As Saturday
From Agreemnt
Where Agreemnt.AStatID = 1 And Agreemnt.DueDate < (Case DatePart(dw, #Today) When '1' Then DateAdd(DAY, -7, DateAdd(DAY, (6 - DatePart(dw, #Today)) % 7, #Today)) When '6' Then #Today Else DateAdd(DAY, (6 - DatePart(dw, #Today)) % 7, #Today) End) And Agreemnt.RentToRent = 0
Group By Agreemnt.STID) As PDRent On store.STID = PDRent.STID
-- Units On Rent
Left Join (Select Invntry.STID,
Cast(Count(Invntry.StockNumber) As Int) As Units
From Invntry
Inner Join AgreHist On Invntry.InvID = AgreHist.InvID And
Invntry.STID = AgreHist.STID
Inner Join Agreemnt On Agreemnt.STID = AgreHist.STID And
Agreemnt.AgreeID = AgreHist.AgreeID And Agreemnt.AStatID =
AgreHist.AStatID
Where Invntry.InvStatID = 11 And Invntry.DisposalDate Is Null And Agreemnt.AStatID = 1
Group By Invntry.STID) As UOR On store.STID = UOR.STID
-- Past Due Units
Left Join (Select Invntry.STID,
Cast(Count(Invntry.StockNumber) As Int) As UnitsPD
From Invntry
Inner Join AgreHist On Invntry.InvID = AgreHist.InvID And
Invntry.STID = AgreHist.STID
Inner Join Agreemnt On Agreemnt.STID = AgreHist.STID And
Agreemnt.AgreeID = AgreHist.AgreeID And AgreHist.AStatID =
Agreemnt.AStatID
Where Invntry.InvStatID = 11 And Invntry.DisposalDate Is Null And
Agreemnt.AStatID = 1 And Agreemnt.DueDate < (Case #TodayNum When '1' Then #PrevSat When '6' Then #Today Else #Saturday End) And Agreemnt.RentToRent = 0
Group By Invntry.STID) As PDUnits On store.STID = PDUnits.STID
-- Reds
Left Join (Select Invntry.STID,
Count(Invntry.StockNumber) As RedsPD
From Invntry
Inner Join AgreHist On Invntry.InvID = AgreHist.InvID And Invntry.STID = AgreHist.STID
Inner Join Agreemnt On Agreemnt.STID = AgreHist.STID And Agreemnt.AgreeID = AgreHist.AgreeID And Agreemnt.AStatID = AgreHist.AStatID
Where Invntry.InvStatID = 11 And Invntry.DisposalDate Is Null And Agreemnt.AStatID = 1 And Agreemnt.DueDate < DateAdd(day, -15, Case Cast(DatePart(dw, #Today) As Int) When '1' Then Cast(DateAdd(DAY, -7, DateAdd(DAY, (6 - DatePart(dw, #Today)) % 7, #Today)) As Date) When '6' Then Cast(#Today As Date) Else Cast(DateAdd(DAY, (6 - DatePart(dw, #Today)) % 7, #Today) As Date) End) And Agreemnt.RentToRent = 0
Group By Invntry.STID) As Reds On store.STID = Reds.STID
Order By Store

running total for each employee

I have the following query which works great to return a running total of carpool reimbursements for an individual staff member. (employee earns $30 for each 20 trips, trips roll over until the end of the year).
-- carpool quarter stats
use TRPTracking
declare #employeeID NVarChar(100), #year Char(4)
Set #employeeID = 'PSmith'
Set #year = '2014'
------
declare #startDate DateTime, #endDate DateTime
Set #startDate = '1/1/' + #year
Set #endDate = DateAdd(d,-1,DateAdd(yyyy,1,#startDate))
DECLARE #calendar TABLE (Date datetime)
WHILE (#startDate <= #endDate) BEGIN
INSERT INTO #Calendar VALUES (#startDate)
SET #startDate = DATEADD(quarter, 1, #startDate)
END
DECLARE #CarpoolTbl TABLE (quarter varchar(250), value decimal(18,1), runningTotal decimal(18,1), earned money)
DECLARE #runningTotal decimal(18,1), #earned money
SET #runningTotal = 0
SET #earned = 0
INSERT INTO #CarpoolTbl
SELECT CASE DatePart(q, c.date)
WHEN 1 THEN 'Jan-Mar'
WHEN 2 THEN 'Apr-Jun'
WHEN 3 THEN 'Jul-Sep'
WHEN 4 THEN 'Oct-Dec' END AS quarter,
IsNULL(Sum(t.value),0) AS value,
null,
0
FROM #calendar c
LEFT OUTER JOIN events e ON (DatePart(q, c.date) = DatePart(q, e.eventDate) AND e.employeeID = #employeeID AND e.eventType = 'CP' AND Year(eventDate) = #year)
LEFT JOIN types t ON t.typeID = e.eventType
GROUP BY DatePart(q, c.date)
UPDATE #CarpoolTbl
SET #earned = earned = Floor((#runningTotal + value)/20) - Floor(#runningTotal/20),
#runningTotal = runningTotal = #runningTotal + value
FROM #CarpoolTbl
SELECT quarter, value, runningTotal, earned * 30 AS earned
FROM #CarpoolTbl
Now, I want a query that returns this information for all employees. I remove the portion that relates to employeeID and I get what looks to be good. But... what is happening is my running total is running for everyone. I need it to restart for each employee. I can't quite figure out where to add the employeeID grouping in the running total.
-- carpool quarter stats
use TRPTracking
declare #year Char(4)
Set #year = '2014'
------
declare #startDate DateTime, #endDate DateTime
Set #startDate = '1/1/' + #year
Set #endDate = DateAdd(d,-1,DateAdd(yyyy,1,#startDate))
DECLARE #calendar TABLE (Date datetime)
WHILE (#startDate <= #endDate) BEGIN
INSERT INTO #Calendar VALUES (#startDate)
SET #startDate = DATEADD(quarter, 1, #startDate)
END
DECLARE #CarpoolTbl TABLE (dateQ int, quarter varchar(250), employeeID varchar(255), value decimal(18,1), runningTotal decimal(18,1), earned money)
DECLARE #runningTotal decimal(18,1), #earned money
SET #runningTotal = 0
SET #earned = 0
INSERT INTO #CarpoolTbl
SELECT
DatePart(q, c.date),
CASE DatePart(q, c.date)
WHEN 1 THEN 'Jan-Mar'
WHEN 2 THEN 'Apr-Jun'
WHEN 3 THEN 'Jul-Sep'
WHEN 4 THEN 'Oct-Dec' END AS quarter,
e.employeeID,
IsNULL(Sum(t.value),0) AS value,
null,
0
FROM #calendar c
LEFT OUTER JOIN events e ON (DatePart(q, c.date) = DatePart(q, e.eventDate)
AND e.eventType = 'CP' AND Year(eventDate) = #year)
LEFT JOIN types t ON t.typeID = e.eventType
GROUP BY e.employeeID, DatePart(q, c.date)
UPDATE #CarpoolTbl
SET #earned = earned = Floor((#runningTotal + value)/20) - Floor(#runningTotal/20),
#runningTotal = runningTotal = #runningTotal + value
FROM #CarpoolTbl
SELECT c.quarter, c.employeeID, a.DisplayName AS employee, c.value AS trips, earned * 30 AS earned
FROM #CarpoolTbl c
LEFT JOIN SBAIntranet.dbo.NTAuth a ON 'SBA\' + c.employeeID = a.AccountName
ORDER BY dateQ, employeeID
Any thoughts?
EDIT:
Unexpected result with running total for all employees, not by employee:
Qtr Employee trips tripsRunningTotal
Jan-Mar Cathy 5.0 5.0
Apr-Jun Cathy 3.0 375.5
Jul-Sep Cathy 4.0 757.0
Jan-Mar Carol 3.5 8.5
Apr-Jun Carol 16.0 391.5
Jul-Sep Carol 44.5 801.5
EDIT 2:
Ok, here is my revised, cleaner, accurate version. Now, to figure out the earned dollars portion.
-- carpool quarter stats
use TRPTracking
declare #employeeID NVarChar(100), #year Char(4)
Set #year = '2014'
------
declare #startDate DateTime, #endDate DateTime
Set #startDate = '1/1/' + #year
Set #endDate = DateAdd(d,-1,DateAdd(yyyy,1,#startDate))
;WITH cte
AS (SELECT Datepart(qq, e.eventDate) AS quarterNum,
CASE DatePart(qq, e.eventDate)
WHEN 1 THEN 'Jan-Mar'
WHEN 2 THEN 'Apr-Jun'
WHEN 3 THEN 'Jul-Sep'
WHEN 4 THEN 'Oct-Dec' END AS quarter,
e.employeeID,
Sum(t.value) AS trips
FROM events e
LEFT JOIN types t ON t.typeID = e.eventType
WHERE e.eventType = 'CP' AND Year(eventDate) = #year
GROUP BY Datepart(quarter, eventDate), e.employeeID)
SELECT a.quarter, a.employeeID, nta.DisplayName AS employee, trips,
(SELECT Sum(trips)
FROM cte b
WHERE a.employeeID = b.employeeID
AND a.quarter >= b.quarter) as runningTotal
FROM cte a
LEFT JOIN SBAIntranet.dbo.NTAuth nta ON 'SBA\' + a.employeeID = nta.AccountName
ORDER BY a.employeeID, a.quarterNum
Use Correlated Subquery to find the running total after grouping by quarter. Inner Join is another option to do this
;WITH cte
AS (SELECT Datepart(qq, dates) qq,
employee,
Sum(trips) trips
FROM Yourtable
GROUP BY Datepart(qq, dates),
employee)
SELECT Employee,
CASE qq
WHEN 1 THEN 'Jan-Mar'
WHEN 2 THEN 'Apr-Jun'
WHEN 3 THEN 'Jul-Sep'
WHEN 4 THEN 'Oct-Dec'
END AS quarter,
Trips,
(SELECT Sum(trips)
FROM cte b
WHERE a.Employee = b.Employee
AND a.qq >= b.qq) Running_Total
FROM cte a
SQLFIDDLE DEMO

sql query get all data from Jan to current month even if there are no records

I'm not good with sql so any help world be great
I have a SQL query that gets records who has register from Jan to current month
My code example
SELECT DatePart(YEAR, p.createStamp) as TheYear, DatePart(MONTH, p.createStamp) as TheMonth , COUNT(p.pId) AS TOTALCOUNT
FROM profile p with(nolock)
where DatePart(YEAR, p.createStamp) = DATEPART(YEAR, GETDATE())
GROUP BY YEAR(p.createStamp), MONTH(p.createStamp)
ORDER BY YEAR(p.createStamp), MONTH(p.createStamp)
how ever the query will bring back
February = 2, March = 3, April = 4 and May = 5
i would like to have it bring back Jan = 1 with a total count of 0 and June = 6 with the total count of 0 as well any ideas how to do this?
thank you.
Here is a loop to create the month/year combinations and use this as the base of your query:
declare #startDate as datetime
set #startDate = '1/1/13'
declare #currentDate as datetime
set #currentDate = '6/6/13'
select
month(#currentDate) as monthOfDate
,year(#currentDate) as yearOfDate
into #allDates
where 1=0
while (#startDate <= #currentDate)
begin
insert into #allDates values (month(#startDate),year(#startDate))
set #startDate = dateadd(m,1,#startDate)
end
select
_monthYear.yearofDate
,_monthYear.monthOfDate
, COUNT(p.pId) as total
from #allDates _monthYear
left join profile p with(nolock)
on month(p.createStamp) = _monthYear.monthOfDate
and year(p.createStamp) = _monthYear.yearOfDate
group by
_monthYear.yearofDate
,_monthYear.montOfDate
drop table #allDates
You can't select what's not there, so I suggest making a lookup table:
CREATE TABLE #Months (Year_ INT, Month_ INT)
GO
SET NOCOUNT ON
DECLARE #intFlag INT
SET #intFlag = 1
WHILE (#intFlag <=20)
BEGIN
--Do Stuff
INSERT INTO #Months
SELECT YEAR(DATEADD(MONTH,#intflag,'20121201')),MONTH(DATEADD(MONTH,#intflag,'20121201'))
SET #intFlag = #intFlag + 1
END
GO
You can change the '20' to be any number of months you want, and change '20121201' in both spots to the month before the month you want to start your lookup.
Then Joining to that table, I believe the following will work:
SELECT m.Year_ as TheYear, m.Month_ as TheMonth , ISNULL(COUNT(p.pId),0) AS TOTALCOUNT
FROM profile p
RIGHT JOIN #Months m
ON DatePart(YEAR, p.createStamp) = m.Year_
AND DatePart(MONTH, p.createStamp) = m.Month_
where DatePart(YEAR, p.createStamp) = DATEPART(YEAR, GETDATE())
GROUP BY m.Year_, m.Month_
ORDER BY m.Year_, m.Month_