You are only looking for records that match that name, so there is currently nothing to count or exclude anything else. You could add a and not exists
clause that queries for any other students; or since it's in your question title, a minus
that does the same:
select a.tutor_user_id, tu.first_name, tu.last_name
from appt a
join tutor t on t.user_id = a.tutor_user_id
join student s on s.user_id = a.student_user_id
join "USER" tu on tu.id = t.user_id
join "USER" su on su.id = s.user_id
where su.first_name = 'John' and su.last_name = 'Smith'
minus
select a.tutor_user_id, tu.first_name, tu.last_name
from appt a
join tutor t on t.user_id = a.tutor_user_id
join student s on s.user_id = a.student_user_id
join "USER" tu on tu.id = t.user_id
join "USER" su on su.id = s.user_id
where not (su.first_name = 'John' and su.last_name = 'Smith');
But I'd do it in one hit using group by
and a having
clause to count the number of appointments for John Smith and for anyone else:
select a.tutor_user_id, tu.first_name, tu.last_name
from appt a
join tutor t on t.user_id = a.tutor_user_id
join student s on s.user_id = a.student_user_id
join "USER" tu on tu.id = t.user_id
join "USER" su on su.id = s.user_id
group by a.tutor_user_id, tu.first_name, tu.last_name
having count(case when su.first_name = 'John' and su.last_name = 'Smith'
then 1 else null end) > 0
and count(case when su.first_name = 'John' and su.last_name = 'Smith'
then null else 1 end) = 0;
SQL Fiddle demo with some simple data, your original query (which also shows duplicates), and both these versions.
As JosephB and Serpiton mentioned, and I forgot to say, you don't actually need to go via the tutor
or student
tables as they aren't really adding anything; you can join to the "USER"
table directly from the appt
columns:
select a.tutor_user_id, tu.first_name, tu.last_name
from appt a
join "USER" tu on tu.id = a.tutor_user_id
join "USER" su on su.id = a.student_user_id
group by a.tutor_user_id, tu.first_name, tu.last_name
having count(case when su.first_name = 'John' and su.last_name = 'Smith'
then 1 else null end) > 0
and count(case when su.first_name = 'John' and su.last_name = 'Smith'
then null else 1 end) = 0;
In both cases I've reworked your original to use ANSI join
syntax rather than the old Oracle style, and removed the subqueries while I was there as all the joining can be done on one level. I would strongly suggest, though, that you rethink your table names so you don't have to use a quoted identifier; maybe call them users
, tutors
and students
instead?