SQLUSA

Microsoft SQL Server 2005 Articles

 

Complex Cross Apply
By Kalman Toth, M.Phil., M.Phil., MCDBA, MCITP
February 10, 2007


The CROSS APPLY operator combines a table or query with a table-valued function operating on the cells of the table or query. CROSS APPLY can be used to construct complex reports.

CROSS APPLY returns only rows from the outer table or query that produce a result set from the table-valued function with cells in the row as input parameters. The CROSS APPLY operator allows you to invoke a table-valued function for each row returned by an outer table or query expression. The table-valued function acts as the right input and the outer table or query expression acts as the left input in an equi-join. The right input is evaluated for each row from the left input and the rows produced are combined for the final output. The list of columns produced by the CROSS APPLY operator is a SELECT subset of the set of columns in the left input followed by the list of columns returned by the right input.

In the following example we calculate financial statistics for each dealer which sells AdventureWorks mountain bikes and associated products.

Here is the listing:

USE tempdb
GO
-- drop FUNCTION dbo.fnOrderFingerprint
CREATE FUNCTION dbo.fnOrderFingerprint(@CustomerID AS int)
RETURNS TABLE
AS
RETURN
SELECT Label='Maximum $', TotalDue=max(TotalDue)
FROM AdventureWorks.Sales.SalesOrderHeader
WHERE CustomerID = @CustomerID
UNION
SELECT Label='Average $', TotalDue=avg(TotalDue)
FROM AdventureWorks.Sales.SalesOrderHeader
WHERE CustomerID = @CustomerID
UNION
SELECT Label='Minimum $', TotalDue=min(TotalDue)
FROM AdventureWorks.Sales.SalesOrderHeader
WHERE CustomerID = @CustomerID
UNION
SELECT Label='Order Count', TotalDue=count(TotalDue)
FROM AdventureWorks.Sales.SalesOrderHeader
WHERE CustomerID = @CustomerID
UNION
SELECT Label='Standard Deviation $', TotalDue=stdev(TotalDue)
FROM AdventureWorks.Sales.SalesOrderHeader
WHERE CustomerID = @CustomerID

GO

SELECT Customer=S.Name,
F.Label,
[Total Due] = left(convert(varchar,convert(money,F.TotalDue),1), len(convert(varchar,convert(money,F.TotalDue),1))-3)
FROM AdventureWorks.Sales.Store AS S
JOIN AdventureWorks.Sales.Customer AS C
ON S.CustomerID = C.CustomerID
CROSS APPLY
tempdb.dbo.fnOrderFingerprint(C.CustomerID) AS F
ORDER BY
Customer ASC, Label DESC

GO

This is the partial report:

Customer Label TotalDue
Excellent Riding Supplies Standard Deviation $ 34,246
Excellent Riding Supplies Order Count 12
Excellent Riding Supplies Minimum $ 34,102
Excellent Riding Supplies Maximum $ 150,167
Excellent Riding Supplies Average $ 94,562
Exceptional Cycle Services Standard Deviation $ 3,978
Exceptional Cycle Services Order Count 4
Exceptional Cycle Services Minimum $ 4,012
Exceptional Cycle Services Maximum $ 13,016
Exceptional Cycle Services Average $ 7,913
Exchange Parts Inc. Standard Deviation $ 3,965
Exchange Parts Inc. Order Count 4
Exchange Parts Inc. Minimum $ 34,610
Exchange Parts Inc. Maximum $ 43,277
Exchange Parts Inc. Average $ 38,982
Exclusive Bicycle Mart Standard Deviation $ 576
Exclusive Bicycle Mart Order Count 6
Exclusive Bicycle Mart Minimum $ 429
Exclusive Bicycle Mart Maximum $ 1,943
Exclusive Bicycle Mart Average $ 1,035

 


 

The Best SQL Server 2005 Training in the World
 
SQLUSA.com Home Page