First use relational selection to keep the Saab cars, then a natural join to find their sales, and finally a relational join to identify the corresponding salespeople. A relational projection gives
The foreign keys ensure that every sale has the referenced car and salesperson. Several qualifying sales by the same person produce just one occurrence of their name under set semantics. Two distinct people with the same name also yield that name only once: this is the requested relational projection onto names.
Find the salesperson identifiers satisfying each price condition using relational selection and relational projection:
Intersect these identifier sets, relational join the result to the salesperson records, and apply relational projection to names:
If intersection is not a primitive of the chosen relational algebra, use with relational difference. There is no need to access Car: the foreign key already ensures that every sale refers to a car.
Intersecting names instead of identifiers is wrong. Two different salespeople called Alex, one making only sales and the other only sales, would make Alex appear in both name sets although neither person satisfies the condition. Nor can one sale satisfy both price tests: the two distinct prices require distinct sale records.
A simple valid database query plan uses a block nested-loop join with the salesperson records on the outside, checking both sale conditions during the same inner scan. It avoids materializing the potentially much larger set of matching sale pairs.
  • Read a block of salesperson records. Retain each empid, its name, and two initially false flags, one for each target price.
  • Scan all of Sales. Apply relational selection to disregard other prices. For each retained sale, match salespersonid against the identifiers in the current outer block, and set the corresponding price flag. Several matching sales only set the same flag again.
  • After the inner scan, output the names of outer records with both flags true. Repeat for the next outer block, then eliminate repeated names to implement set semantics.
Let be the actual number of salesperson data pages and the number of outer data pages that fit along with the flags and working buffers. With the usual convention of outer pages, one inner input page and one output page, take for . If flag storage requires an extra reserved page, reduce accordingly. The number of outer records is at most , and there are outer blocks. Every such block requires a complete scan of the sales data pages.
Count a database page read or write as one I/O. Conservatively charge to locate the first salesperson leaf and to locate the start of each inner scan; this permits a small double charge if a definition of height includes a data leaf. The estimated read cost is
In the common convention that scan startup and cached internal pages are ignored, the usual upper estimate is
For an empty outer input there are no inner scans. This database query plan requires neither a sorted sale input nor a price index. In particular, the clustered database index on invoiceno cannot locate records by price. The quantities and describe the amount of qualifying data; they do not justify replacing a complete scan cost by . They can bound the retained work within each scan by roughly sale records, if those page counts describe packed qualifying records. Comparison cost against the outer block is CPU work rather than additional I/O.
Finally let be the extra I/O for eliminating repeated output names, including any temporary writes and reads, and let be the final result size in database pages if materialization is required. The total estimate is
If enough additional memory is available to retain all distinct qualifying names while producing the stream, then . This extra memory is an additional assumption, separate from the join buffers. More generally, for pages of raw qualifying names, external merge sort gives for , including spooling. Names can be deduplicated during the merges. Counting this work matters because a database primary key on empid does not make names unique. No claim of optimality is needed for this database query plan.