Reputation: 325
I have a query in a database using SQL Azure, which returns a set of sales figures, month by month, for a set of offices and staff within those offices, as in the image below: The query which returns this is called vwOfficeAndNegSalesTotals and looks like this:
SELECT OfficeID, DATENAME(Month,PipelineDate) + ' ' + DATENAME(Year,PipelineDate) as [PipelineMonth], OfficeName, Negotiator, Status, SUM(Fee) as FeeValue FROM vwBankingProjections GROUP BY OfficeID, DATENAME(Month,PipelineDate) + ' ' + DATENAME(Year,PipelineDate), OfficeName, Negotiator, Status, DATEPART(Month,PipelineDate), DATEPART(YEAR,PipelineDate)
I need to add another column, which provides a running total of FeeValue for the year to date for the Negotiator in that row, with the year "to date" meaning up to and including the month of that row. Additionally, it should only total the FeeValue where the status is Payment received.
So, it would return something like this:
As you can tell from the structure of vwOfficeAndNegSalesTotals, the query upon which it is based (vwBankingProjections) does include actual dates, rather than just the text Month + Year - these dates are in the PipelineDate column.
My first attempt got me a total for the year which viewing a row for May 2016 (at time of writing) would be the year to date, but it needs to only show the total for the year to the date mentioned in that row (so if viewing a row for April 2016, would be the total from Jan - April 2016). In case it's of any help, here's what I came up with for that:
SELECT OfficeID, DATENAME(Year,PipelineDate) as [PipelineYear], OfficeName, Negotiator, SUM(Fee) as YTDFee FROM vwBankingProjections WHERE Status IN ('Payment Received') GROUP BY OfficeID, DATENAME(Year,PipelineDate), OfficeName, Negotiator
If anyone can help, I'd be grateful, as this is a bit beyond my skill-set.
Thanks a lot
Andrew
Upvotes: 2
Views: 1027
Reputation: 1482
You can use SUM() OVER().
Create and populate table.
CREATE TABLE dbo.Sales
(
OfficeID int NOT NULL,
PipelineMonth date NOT NULL
CHECK (DAY(PipelineMonth) = 1),
OfficeName nvarchar(25) NOT NULL,
Negotiator nvarchar(25) NOT NULL,
[Status] nvarchar(25) NOT NULL,
FeeValue int NOT NULL,
FeeValueReceived AS IIF([Status] = N'Payment received', FeeValue, 0)
);
GO
INSERT INTO dbo.Sales (OfficeID, PipelineMonth, OfficeName, Negotiator, [Status], FeeValue)
VALUES
(1, '2016-01-01', N'London', N'Fred', N'Payment received', 5000),
(1, '2016-01-01', N'London', N'Fred', N'Completed', 4800),
(1, '2016-01-01', N'London', N'Kate', N'Payment received', 5980),
(1, '2016-01-01', N'London', N'Kate', N'Completed', 7000),
(1, '2016-01-01', N'London', N'Bob', N'Payment received', 9250),
(2, '2016-01-01', N'Birmingham', N'Jo', N'Payment received', 7870),
(2, '2016-01-01', N'Birmingham', N'Kathryn', N'Payment received', 3690),
(2, '2016-01-01', N'Birmingham', N'Kathryn', N'Completed', 8545),
(1, '2016-02-01', N'London', N'Fred', N'Payment received', 6500),
(1, '2016-02-01', N'London', N'George', N'Completed', 2575),
(1, '2016-02-01', N'London', N'George', N'Payment received', 7500),
(1, '2016-02-01', N'London', N'Kate', N'Payment received', 8393),
(1, '2016-02-01', N'London', N'Bob', N'Payment received', 6125);
Then make a SELECT statement with SUM() OVER().
SELECT OfficeID, PipelineMonth, OfficeName, Negotiator, [Status], FeeValue,
SUM(FeeValueReceived) OVER (PARTITION BY OfficeID, Negotiator, YEAR(PipelineMonth) ORDER BY PipelineMonth, [Status] DESC, FeeValue DESC) AS 'YTD'
FROM dbo.Sales
ORDER BY PipelineMonth, OfficeID, Negotiator, [Status] DESC, FeeValue DESC
See Books Online > OVER Clause (Transact-SQL): https://msdn.microsoft.com/en-us/library/ms189461.aspx
Upvotes: 1
Reputation: 56
RichardCL has a solid approach. If you need a true RunningTotal, see the following examples in https://devjef.wordpress.com/2012/10/20/calculating-running-totals/
Upvotes: 0