Josh Trutwin <[EMAIL PROTECTED]> wrote on 09/20/2004 10:41:46 PM:

> On Mon, 20 Sep 2004 10:25:16 -0400
> [EMAIL PROTECTED] wrote:
> 
> > I think you missed my point. I think the 5.0.1 behavior was correct
> > and the others are wrong. There is a known bug (or two) about mixing
> > outer joins and inner joins and it looks like it may be fixed. IF
> > you want to see all of the students THAT TABLE (students) needs to
> > be on the LEFT side of a LEFT JOIN or the RIGHT side of a RIGHT
> > JOIN. That's what the directions mean....
> 
> Interesting - do you have a link to more information on this bug?
> 

http://bugs.mysql.com/1677 and http://bugs.mysql.com/1591 and 
http://bugs.mysql.com/3765

> > SELECT s.tech_id, s.full_name, sa.points_awarded, sa.date_submitted
> > FROM student s
> > INNER JOIN enrollment e 
> >         ON e.tech_id = s.tech_id
> >         AND e.term_id = '3'
> > LEFT JOIN submitted_assignment sa 
> >         ON sa.tech_id = s.tech_id 
> > LEFT JOIN assignment a 
> >         ON a.a_id = sa.a_id 
> >         AND a.a_id = '100'
> > ORDER BY s.full_name;
> > 
> > I also moved the clause "AND a.a_id = '100'" into the ON portion of
> > the LEFT JOIN. That way you can see who did and didn't get that
> > assignment.
> > 
> > If you describe what you WANT to see, I can help you write the query
> > to get it. What I think I wrote for you will be "all students where
> > term_ID=3 and what grades they got on assignment 100." But i think
> > you may get some duplicate rows of blank scores. Does "assignment"
> > relate to "student", perhaps with a tech_id or student_id field?
> > That fixes one dilemma by setting up the following query
> > 
> > SELECT s.tech_id, s.full_name, if(isnull(a.a_ID),'no','yes') as 
> > assigned_100, sa.points_awarded, sa.date_submitted
> > FROM student s
> > INNER JOIN enrollment e 
> >         ON e.tech_id = s.tech_id
> >         AND e.term_id = '3'
> > LEFT JOIN assignment a 
> >         ON a.student_ID = s.student_ID
> >         AND a.a_id = '100'
> > LEFT JOIN submitted_assignment sa 
> >         ON sa.tech_id = s.tech_id 
> >         AND a.a_id = sa.a_id 
> > ORDER BY s.full_name;
> 
> This is what I eventually used:
> 
> SELECT s.tech_id, s.full_name, 
>    sa.points_awarded, sa.date_submitted
> FROM student s
> INNER JOIN enrollment e 
>         ON e.tech_id = s.tech_id
> LEFT JOIN submitted_assignment sa 
>        ON sa.tech_id = s.tech_id AND sa.a_id = '$a_id'
> LEFT JOIN assignment a 
>        ON a.a_id = sa.a_id
> WHERE e.term_id = '3'
> ORDER BY s.full_name;
> 
> It didn't seem to work with the "AND sa.a_id = '$a_id'" in the 
> assignment join condition - but this works.  I don't understand why 
> that doesn't filter the right rows if it's in the WHERE clause, I 
> usually define my JOIN condition solely on the column(s) being 
> joined together and any additional filtering gets done in the WHERE 
clause.
> 

There are up to three layers of record filtering that happen during any 
query. First is the JOIN filtering.  That is where the ON conditions are 
used with the table declarations to build a virtual table that consists of 
all columns from each of the participating tables and each combination of 
rows that meets the ON conditions.  If table A has 5 rows and table B has 
50 rows and the ON conditions force a match of at most 2 records from 
table B to each record in table A, the virtual table will have at most 10 
rows (not the 250 that would be generated without the ON conditions). 
Second to be applied is the rest of the WHERE clause that could not be 
applied during the ON determinations. This is especially true with queries 
that contain OUTER JOINS. If it didn't happen in this order, we couldn't 
do an outer join of two tables and look for a null result in the outer 
table to determine non-matching rows. The third set of filters to be 
applied comes from the HAVING clause. HAVING conditions are applied after 
every other portion of the query has been analyzed except for the LIMIT 
clause. That is why HAVING works on the results of GROUP BY aggregate 
functions and can use column aliases declared in the SELECT clause.

When you put a condition into the ON clause of a JOIN, it is going to be 
applied to the formation of the virtual table which gets computed _before_ 
the entire WHERE clause is applied. Under many conditions, some WHERE 
conditions can also be applied to table JOINs along with the ON 
restrictions. Luckily, the query optimizer handles that for us.

http://dev.mysql.com/doc/mysql/en/LEFT_JOIN_optimization.html
http://dev.mysql.com/doc/mysql/en/Where_optimizations.html

I am glad you have it working. Come back if you run into any more trouble.

Shawn Green
Database Administrator
Unimin Corporation - Spruce Pine
> Man, I thought I had a good handle on OUTER JOINs.  Erg.
> 
> Josh
> 
> 
> 
> -- 
> MySQL General Mailing List
> For list archives: http://lists.mysql.com/mysql
> To unsubscribe:    http://lists.mysql.com/[EMAIL PROTECTED]
> 

Reply via email to