tags:

views:

98

answers:

2

I'm sure there must be a simple way to do this, but I've been tearing my hair out for hours now and I'm getting nowhere. Here is a working query from a customer listing utility:

SELECT c.customer_ID, title, surname, forenames, COUNT(booking_ID) AS bookings
FROM customer c 
LEFT JOIN booking b 
ON c.customer_ID = b.customer_ID
WHERE customer_Live
GROUP BY c.customer_ID, surname, forenames, title
ORDER BY surname;

Here is the problem: the COUNT returns all of the related bookings. But the booking table has a 'booking_Live' column which is set to false whenever a booking is cancelled. What I need to do is somehow exclude cancelled bookings from the count; so if all a customer has is cancelled bookings, it will return 0. I've tried putting a HAVING clause on the group, but that just ends up removing any customers with zero live booking from the output.

+2  A: 

A subquery should resolve your issue. Something like this.

SELECT c.customer_ID, title, surname, forenames, COUNT(booking_ID) AS bookings
FROM customer c 
LEFT JOIN (SELECT customer_ID, booking_id FROM Booking WHERE booking_live = true) as b 
ON c.customer_ID = b.customer_ID
WHERE customer_Live
GROUP BY c.customer_ID, surname, forenames, title
ORDER BY surname;
KevenDenen
Apologies, I inadvertently posted to the wrong answer. Although I've checked yours and it also works. Thanks.
Antagony
This also excludes any customers who have only cancelled bookings.
David-W-Fenton
+1  A: 

Maybe I didn't get it well but why don't you use:

SELECT c.customer_ID, title, surname, forenames, COUNT(booking_ID) AS bookings
FROM customer c 
LEFT JOIN booking b 
ON (c.customer_ID = b.customer_ID AND b.booking_Live = true)
WHERE customer_Live
GROUP BY c.customer_ID, surname, forenames, title
ORDER BY surname;
Kamyar
You can't do that in MS Access.
Remou
Yes, that worked straight away! I tried something like that earlier, but I couldn't get the syntax right. Thank you.
Antagony
@Remou: I don't whether it's the version of access (2007), or Jet (4)--or because it's an external app using ADO--but it does work.
Antagony
It works... You just have to put your conditions for your join in parenthesis.
Kamyar
Remou
Nope, the back end is a standard mdb database. The front end is an external application. I've tested it myself within Access 2007 and it runs just fine if I enter the SQL directly. But it won't display in design view, stating it can't represent the join expression.
Antagony
I don't understand why this is being done in a JOIN instead of in the WHERE clause.
David-W-Fenton
@David: How are you going to do this in the WHERE clause and have it show all customers regardless of whether they have live bookings or not?
KevenDenen
@David-W-Fenton I would be grateful if you had time to test the join illustrated, because I cannot see how it would work with Access 2007 but not with 2010.
Remou
@Remou: I've tried playing around within Access to see if I can get it to raise the error you've described, and I can't. The only anomaly I've noticed--and this is something anyone using this solution will need to be aware of--is that Access 2007 runs the query okay, but when you re-examine it in SQL view, it has removed the parentheses. Curiously, it still runs okay. But if you try to edit it, or even just re-save it, it throws up a "Join expression not supported" error; which can then only be fixed by re-adding the parentheses.
Antagony
@Kamyar Is it possible for you to make a sample database with this query available, please?
Remou
Remou, In case Kamyar doesn't respond: I've knocked together a small [sample database](http://filevo.com/9hregvhj9ydi.html) with the query in it. I've also added a vbscript file, which writes the same query for itself (rather than using the saved query). Both are working for me.
Antagony
@Antagony Thank you. It grows more curious. I still get the error with the file you sent and Access 2010 for both VBScript and query design. The odd thing is, I would not expect this join to work in Access.
Remou
That's very strange Remou. I wonder if anyone else could test this with an Access 2010 installation. I've just tested it on an old XP machine running Access 2003 and it worked okay on that too. But I'm a bit concerned now about future compatibility if I stick to using this method. I'm beginning to think KevenDenen's method might be a safer bet.
Antagony
I asked about why this is done in a JOIN and not in the WHERE clause and the answer was that the WHERE clause allowed the Customers without bookings to show up, but this is just not true. `booking_Live = true` in either a JOIN or a WHERE clause is going to eliminate the ones without a live booking. The sample database demonstrates this, as CustomerID 3 does not show up in the results.
David-W-Fenton
@David: The **LEFT** JOIN means it includes **all** of the customer records--showing zero for customers with no live bookings--which is what I need. An INNER JOIN would do what you're describing.
Antagony
@Antagony I think all is well. I was testing on the 2010 beta and installed the new 2010. I do not know whether it was the reinstall or the new version, but the query is now working for me. Thanks everyone.
Remou
Looking again, I also find, along with David, that customers 3 and 7 are missing from the list. The inclusion of `b.booking_Live = true` means that customers with no bookings are excluded, as far as I can tell. There is only one customer with a zero count, and that is Sarah Hatton (9), who has a cancelled booking.
Remou
Yes, that's right. What I *should* have said was it includes all **live** customers. Putting the criteria in a WHERE clause would result in excluding *any* customer with no live booking.
Antagony
Okay, I was not paying sufficient attention :)
Remou