I don't see that what MW says can apply in your case as it would mean that no
rows would be returned whether you use the IN or NOT IN predicates as the
subquery is exactly the same in each case. Also what he says does not match
my own experience.
I can see no obvious explanation for the behaviour you are experiencing. I
think you can probably exclude the [Company Type]="C" criterion from the
subquery's WHERE clause, but the NOT IN predicate should have worked as you
expect even so. Better than the NOT IN predicate, however, would be to use
the NOT EXISTS predicate:
SELECT *
FROM Clients
WHERE NOT EXISTS
(SELECT *
FROM Contacts
WHERE Contacts.[Company ID] = Clients.ID);
You could of course leave the [Company Type]="C" criterion in the above
subquery and it should still work, but it looks to me like its unnecessary.
As regards the solution by PL, I can only assume that you must have omitted
the [Company Type] ="C" criterion for it to work, in which case it’s the best
solution, though its usual to examine the primary key column of the table on
the outer side of the join for IS NULL, not the foreign key. Otherwise, as
posted with the inclusion of the [Company Type] ="C" criterion, it should
return zero rows. This is because with that criterion included it restricts
the query on a column in the table on the outer side of the left outer join.
An outer join can only be restricted on a column in the table on the inner
side. This makes sense, as if you think about the logic underlying an outer
join, you can’t return rows from one table on the basis a criterion based on
values in rows in another table which don't actually exist. In fact all it
does is cause the query to behave as if the join is an INNER JOIN.
If you have used the query exactly as posted by PL and it does return rows,
then it would appear to be defying logic! I'd be very interested to know if
this is the case, but unfortunately I'll be away incommunicado from now for a
while, so my apologies in advance if you do respond to this post and don't
hear back from me. Bearing in mind the inexplicable behaviour you are
experiencing in use of the IN or NOT IN predicates and a subquery, however,
nothing would surprise me.
I do wonder whether there is something about the design of the tables which
might explain the strange behaviour. I notice that you have a Company Type
column in Contacts, but that would seem to me to be an attribute of Clients
rather than Contacts, judging by the fact that the latter includes a Company
column.
Ken Sheridan
Stafford, England
John said:
Hi
Thanks. Did that and worked. I wasn't too worried about the performance as
it is an adhoc query but its still puzzling why Not In version did not work.
Thanks again.
Regards
Hi
Access 2000 SP3. I have a Clients table which has 5400 records.When I run
the below query to return all records in Clients table that have matching
keys in Contacts table then I get 4047 records.
SELECT Clients.ID, Clients.Company
FROM Clients
WHERE (((Clients.ID) In (SELECT Contacts.[Company ID] FROM Contacts WHERE
(((Contacts.[Company Type])="C")))));
When I run the below query to return all records in Clients table that DO
NOT have matching keys in Contacts table then I expect to get 1353
(5400-4047) records;
SELECT Clients.ID, Clients.Company
FROM Clients
WHERE (((Clients.ID) Not In (SELECT Contacts.[Company ID] FROM Contacts
WHERE (((Contacts.[Company Type])="C")))));
However I get 0 (nill) records. What is the problem and how can I make the
query work to return all records in Clients table that do not have any
matches in Contacts table?
Thanks
Regards
using NOT IN with a subselect is going to have hideous performance
with large datasets. Use an outer join instead. Use the Find
Unmatched query wizard, and the wizard will build the query for you.
something like...
SELECT Clients.ID, Clients.Company
FROM Clients LEFT JOIN Contacts ON Clients.ClientID=Contacts.[Company
ID]
WHERE Contacts.[Company Type]="C"
AND Contacts.[Company ID] IS NULL;