Joining Tables and Queries

In addition to joins based on permanent tables, Microsoft Jet supports joins between tables and saved queries, or even between two queries. Queries can be based on other queries, which can further be based on other queries, and so on. Microsoft Jet automatically resolves all references to queries and tables.

Microsoft Jet QueryDef objects can be treated, for the most part, as if they were tables in the database. A QueryDef object performs the function of a view in SQL. QueryDef and TableDef objects occupy the same “name space” within a Microsoft Jet database. This means that you can’t have a TableDef object and a QueryDef object with the same name, for example. Generally, wherever you can use a base table, you can use a query based on that table instead.

Suppose you want to find the percentage of your total sales of certain products that were generated by particular customers. One way to do this is to create the four queries shown in this section. The first query totals orders by customer and product:

SELECT 
	Orders.CustomerID, 
	[Order Details].ProductID, 
	Sum((UnitPrice*Quantity) - (Discount*(UnitPrice*Quantity))) AS ExtPrice 
FROM Orders 
INNER JOIN [Order Details] 
ON Orders.OrderID = [Order Details].OrderID 
GROUP BY Orders.CustomerID, [Order Details].ProductID;

Save this query as a permanent QueryDef object in the database with the name SelectCustomersOrdersTotals. You can now treat this query as if it were a table. The sample output it produces may be:

Customer Product ExtPrice
ALFKI Aniseed Syrup $ 60.00
ALFKI Grandma’s Boysenberry Spread $399.95
ALFKI Rössle Sauerkraut $774.95
ALFKI Chartreuse verte $377.75
ALFKI Spegesild $ 23.75

Now you have to find the order totals for each ProductID value. Create a permanent QueryDef object called SelectOrdersTotals with the following SQL statement:

SELECT 
	[Order Details].ProductID, 
	Sum((UnitPrice*Quantity) - Discount) AS ExtPrice 
FROM Orders 
INNER JOIN [Order Details] 
ON Orders.OrderID = [Order Details].OrderID 
GROUP BY [Order Details].ProductID;

Part of the output produced by this query may be:

Product ExtPrice
Chai $14,274.65
Chang $18,554.70
Aniseed Syrup $ 3,079.80
Chef Anton’s Cajun Seasoning $ 9,423.30
Chef Anton’s Gumbo Mix $ 5,800.40

Now you can create a third QueryDef object called SelectPercentOfTotal, which joins SelectOrdersTotals with SelectCustomersOrdersTotals:

SELECT 
	SelectCustomersOrdersTotals.CustomerID, 
	SelectCustomersOrdersTotals.ProductID, 
	SelectCustomersOrdersTotals.ExtPrice AS CustTotal, 
	SelectOrdersTotals.ExtPrice AS ProdTotal, 
	Format(CustTotal/ProdTotal, '#.###') AS PercentOfTot 
FROM SelectOrdersTotals 
INNER JOIN SelectCustomersOrdersTotals 
ON SelectOrdersTotals.ProductID = SelectCustomersOrdersTotals.ProductID;

Part of the output from this query may be:

Customer Product CustTotal ProdTotal PercentOfTot
Alfreds Futterkiste Aniseed Syrup $ 60.00 $ 3,079.80 .019
Alfreds Futterkiste Grandma’s Boysenberry Spread $399.95 $ 7,344.63 .054
Alfreds Futterkiste Rössle Sauerkraut $774.95 $26,864.35 .029
Alfreds Futterkiste Chartreuse verte $377.75 $13,148.80 .029
Alfreds Futterkiste Spegesild $ 23.75 $ 6,142.28 .004

Finally, you can join this third QueryDef object back to the Customers and Products tables to pick up the CompanyName and ProductName fields:

SELECT 
	SelectPercentOfTotal.*, 
	Products.ProductName, 
	Customers.CompanyName 
FROM (SelectPercentOfTotal 
	INNER JOIN Customers 
	ON SelectPercentOfTotal.CustomerID = Customers.CustomerID) 
INNER JOIN Products 
ON SelectPercentOfTotal.ProductID = Products.ProductID;