views:

159

answers:

3

I am trying to find the fastest way to find all of the records in a parent table that do not have certain records in a child table. For example, I want the query to return all of the family records where there are no male children or no children at all.

Example 1

This is painfully slow:

SELECT * FROM Families
WHERE Families.FamilyID NOT IN(SELECT FamilyID FROM Children WHERE Children.Gender="m")

Example 2

This is faster:

SELECT * FROM Families
WHERE NOT EXISTS(SELECT * FROM Children WHERE Children.Gender="m" AND Children.FamilyID = Families.FamilyID)

Example 3

This is the fastest, but I'm worried about investing in it because I can't find any documentation on it. I don't even know what it's called. For want of a better term, we have been calling it an "anonymous query".

SELECT * FROM Families
LEFT JOIN
[SELECT * FROM Children WHERE Gender="m"]. AS AliasChildren ON Families.FamilyID=AliasChildren.FamilyID
WHERE AliasChildren.FamilyID IS NULL

So my question is this:

  1. What is this thing called in example 3?
  2. Is it a "mainstream" feature of Access that will be supported in the future?
  3. Where can I find documentation on it (this might be easier once I know what it's called)?

Thanks!

+3  A: 

What is this thing called in example 3?
It is called a "Derrived table"

Is it a "mainstream" feature of Access that will be supported in the future?
It is a standard feature of ANSI SQL as far as I know and is very commonly used.

Where can I find documentation on it (this might be easier once I know what it's called)? Here is a blog article about them

In any case the query posed by Mitch is your best bet:

SELECT *   
FROM Families   
LEFT JOIN Children  
  ON (Families.FamilyID = Children.FamilyID) AND (Children.Gender="m")  
WHERE (Children.FamilyID IS NULL)
JohnFx
3000 today for you hopefully :)
Michael Pryor
Thanks, John - for both the name of the thing and the blog. My crazy syntax with the square brackets works, but so does normal syntax with parentheses.
Shane
That syntax is a little strange. I suggest going with the more standard syntax with parenthesis. The square brackets is probably an Access specific thing.
JohnFx
If you're writing your SQL in Access and it's not a passthrough query, you will use the Jet SQL syntax. What that is depends on which ANSI mode you're using in Access, 92 (using parens) or 89 (the default, using the brackets).
David-W-Fenton
@David - Just mentioning the word "ANSI" is helpful because it's a starting place to find more info. I appreciate your comment.
Shane
I think you corrected yourself in error. Consider this quote from the SQL-92 Standard: "A derived table is a table derived directly or indirectly from one or more other tables by the evaluation of a <query expression>."
onedaywhen
Good catch, onedaywhen. Uncorrected. =)
JohnFx
A: 

I think you could also try something like this:

SELECT * FROM Families WHERE Families.FamilyID IN ( SELECT Children.FamilyID FROM Children WHERE Children.Gender<>'m' GROUP BY Children.FamilyID )

aintnoprophet
+5  A: 

Example 3 is termed a derived table, but you can simplify the query to this:

SELECT * FROM Families
LEFT JOIN
Children ON Families.FamilyID = Children.FamilyID AND Children.Gender="m"
WHERE Children.FamilyID IS NULL
Mitch Wheat
Excellent, Mitch. Thank you. I just tried it and got it to work after adding the parentheses.SELECT * FROM FamiliesLEFT JOINChildren ON (Families.FamilyID = Children.FamilyID AND Children.Gender="m")WHERE Children.FamilyID IS NULL
Shane
Beware that in access the derived table must be in () but the moment you save the query, access kindly changes them to the []. you have in your example - which will not work. So each time you edit the qry you have to the the []. back to (). It's irritating but functional.
Praesagus
Also, you should select this as the answer - as it is the best one. :)
Praesagus
@Shane: sorry about; that I tested in SQL Server!
Mitch Wheat
@Mitch - Certainly no apology necessary. I appreciated that you made effort to really understand the problem - so much so that you were able to offer a solution to the problem, not just an answer to the question being asked.
Shane
If you're using ANSI 92 mode in Access, it will use (). The "[]. AS alias" is Jet's dialect ANSI 89 for the same thing. It causes problems if the SELECT statement inside the [] has object names that require brackets. There are two solutions: use better naming conventions and/or switch to ANSI 92.
David-W-Fenton
IMO the () syntax is preferable. Actually, ANSI-92 Query Mode is my overall preference, especially for its richer SQL DDL syntax.
onedaywhen