CTE Running Total Example

I happened across a CURSOR based “Running Total” example on the web today.
Everyone with whom I work knows I detest Cursors in TSQL. 

So I coded up (one) alternate solution.

Below is (one variation) of a ‘Running Total’ solution using a CTE.
http://technet.microsoft.com/en-us/library/ms175972.aspx  (CTE Link)

———–START TSQL

Use NorthwindGO

declare @CustomerID varchar(6)

declare @BeginDate datetime

declare @EndDate datetime

select @CustomerID = (select top 1 CustomerID from dbo.Orders )

select @BeginDate = ’01/01/1900′

select @EndDate = ’12/31/2010′

;
WITH
MyCTE /* http://technet.microsoft.com/en-us/library/ms175972.aspx */
( ShipName,ShipAddress,ShipCity,ShipRegion,ShipPostalCode,ShipCountry,CustomerID,CustomerName,[Address],
City,Region,PostalCode,Country,Salesperson,OrderID,OrderDate,RequiredDate,ShippedDate,ShipperName,
ProductID,ProductName,UnitPrice,Quantity,Discount,ExtendedPrice,Freight,ROWID) AS
(
SELECT
ShipName ,ShipAddress,ShipCity,ShipRegion,ShipPostalCode,ShipCountry,CustomerID,CustomerName,[Address]
,City ,Region,PostalCode,Country,Salesperson,OrderID,OrderDate,RequiredDate,ShippedDate,ShipperName
,ProductID ,ProductName,UnitPrice,Quantity,Discount,ExtendedPrice,Freight
, ROW_NUMBER() OVER ( ORDER BY OrderDate , ProductName ASC ) as ROWID
FROM
dbo.Invoices inv /* “Invoices” is a VIEW, FYI */
where
inv.CustomerID = @CustomerID and (inv.OrderDate between @BeginDate and @EndDate)
)
SELECT
/*
ShipName,ShipAddress,ShipCity,ShipRegion,ShipPostalCode,ShipCountry,CustomerID,CustomerName,[Address],
City,Region,PostalCode,Country,Salesperson,OrderID,OrderDate,RequiredDate,ShippedDate,ShipperName,
ProductID,ProductName,UnitPrice,Quantity,Discount,ExtendedPrice,Freight,
*/

/*trim the list down a little for the final output */

CustomerID ,Salesperson,OrderID,OrderDate,ProductName,UnitPrice,Quantity,Discount,ExtendedPrice,Freight,(ExtendedPrice + Freight) as ComputedTotal

/*The below line is the “trick”. I reference the above CTE, but only get data that is less than or equal to the row that I am on (outerAlias.ROWID)*/
, (Select SUM (ExtendedPrice + Freight) from MyCTE innerAlias where innerAlias.ROWID <= outerAlias.ROWID ) as RunningTotal
, ROWID as ROWID_SHOWN_FOR_KICKS , OrderDate as OrderDateASecondTimeForConvenience
FROM
MyCTE outerAlias

/*Two Order By Options*/
ORDER BY outerAlias.OrderDate , ProductName

/* << Whatever the ORDER BY is here, should match the “ROW_NUMBER() OVER ( ORDER BY ________ ASC )” statement inside the CTE */
/*ORDER BY outerAlias.ROWID */ /* << Or, to keep is more “trim”, ORDER BY the ROWID, which will of course be the same as the “ROW_NUMBER() OVER ( ORDER BY” inside the CTE */

Advertisements
This entry was posted in Software Development. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s