It sounds like what you want is a list of customers and the distinct books that they've bought. I'd rewrite the query like this, which ought to do what you want:
select c.customer_first_name ,
c.customer_last_name ,
c.customer_numb ,
b.author_name ,
b.title
from customers c
left join ( select distinct
o.customer_numb ,
ol.isbn
from orders o
left join order_lines ol on ol.order_number = orders.order_numb
) cb on cb.customer_numb = c.customer_numb
join books b on b.isbn = cb.isbn
where c.customer_numb = 6
If you want a count of how many of each title they've bought, change the derived table (aka inline view or virtual table) in the from clause to use group by
rather than select distinct
and add the appropriate aggregate function to the result set.
Here's where your original query goes south: every column in the result set must be either
- a column or expression in the
group by
clause,
- a literal, or ...
- an aggregate function
While there are some exceptions here (for instance, you can have an expression dependent solely on grouping columns and aggregate functions), and whilst the SQL Standard putatively allows other columns, most implementations do not.
Consider a query like this, where you have a one-to-many relationship between customer and order, where individual orders might be shipped to a one address or another.
select c.customer_id , o.shipping_address , orders = count(*)
from customer c
join order o on o.customer_id
group by c.customer_id
What is the semantic meaning of o.shipping_address
in this context? You've grouped the orders by customer id and collapsed the entire group into a single row. customer_id
is easy, since that's the grouping criteria: the entire group, by definition shares the same value for it. count(*)
is easy, too, since it's merely a count of the rows in the group.
'shipping_address' is a problem, though: the group might well have multiple values for shipping address, but the aggregated group can only return one value. First? Last? something else?
SQL Server used to have a very nonstandard implementation that allowed such oddball stuff. What it did in this case is to essentially aggregate the group into a single row and then join that aggregated across each row across all the rows in the group. Not exactly intuitive behaviour.