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;