简体   繁体   中英

How do a write a left join with a where clause restricting the left-hand portion across multiple tables?

I'm trying to write an SQL query that will gather certain data in one table, based on data across several other tables. That part was easy enough. Unfortunately, I also need to recover data from a second table, and that needs to be done with a left join.

If I just do a left join, eg

select *
from table_A A
left join table_B B on A.id=B.id

everything is fine. I can add in a where clause safely enough, like

where A.id>5

The issue occurs when I try to have more than one table on the left hand side, for example

select *
from table_A, table_C
left join table_B on A.id=B.id
where table_A.id=table_C.id

All of a sudden, A.id is no longer a recognized column. I tried changing it so that I have select A.id as foo, and then do on foo=B.id, but foo isn't recognized either. ( Unknown column 'bla' in 'on clause')

While there are many references out there than explain how to do a join clause, and some examples even use a simple where clause, I can't find any that combine a join clause, a where clause, and multiple tables on the left hand side.

For background on the question:

My original query was:

select SQL_CALC_FOUND_ROWS tutor_user.username
    , tutor_user.userid
    , tutor_tutor.rate
    , tutor_user.username 
from tutor_user
    , tutor_attends
    , tutor_tutors_in
    , tutor_subject
    , tutor_tutor 
where tutor_user.userid=tutor_attends.userid 
    and tutor_attends.schoolid=80 
    and tutor_tutors_in.userid=tutor_user.userid 
    and tutor_tutors_in.subjectid=tutor_subject.subjectID 
    and tutor_subject.name='Aerospace Studies' 
    and tutor_tutor.userid=tutor_user.userid //ERROR
LIMIT 0, 15

Unfortunately, there's no guarantee that tutor_tutor information will exist for every user -- a minor flaw that's persisting from poor decisions early on in the website/database design cycle. So, the easy solution is to turn it into a join.

The problem is, I can't find any good tutorials explaining how to combine a join with where clauses. My best effort comes up with the following:

select SQL_CALC_FOUND_ROWS tutor_user.username
    , tutor_user.userid
    , tutor_tutor.rate
    , tutor_user.username 
from tutor_user
    , tutor_attends
    , tutor_tutors_in
    , tutor_subject
LEFT JOIN tutor_tutor
    on tutor_user.userid=tutor_tutor.userid
where tutor_user.userid=tutor_attends.userid 
    and tutor_attends.schoolid=80 
    and tutor_tutors_in.userid=tutor_user.userid 
    and tutor_tutors_in.subjectid=tutor_subject.subjectID 
    and tutor_subject.name='Aerospace Studies' 
    LIMIT 0, 15

Ideally, you shouldn't mix the lazy join syntax ( select ... from a,b,c ) with the more specific select ... from a join B ... join c ... . And doing a select * can be problematic as well, especially you're not going to be using all of the fields, or need to refer to the fields by name instead of position.

So your query should be:

SELECT A.field, A.otherfield, B.field, B.otherfield, C.yetanotherfield
FROM table_A AS A
JOIN table_B as B on A.id = B.a_id
JOIN table_C as C on B.id = C.b_id
WHERE ...

You can put multiple clauses in the JOIN eg

SELECT * 
FROM table_a A
    LEFT OUTER JOIN table_b B
        ON A.col1 = B.col1 
             AND A.col2 = B.col2
             AND B.col3 > 5

You can write the criteria in the where clause, but that is outdated notation. If you do, however, want to pu the join clause in the WHERE anyway then add an OR to handle NULL otherwise it ceases to be a LEFT JOIN

eg

SELECT * 
FROM table_a A
    LEFT OUTER JOIN table_b B
        ON A.col1 = B.col1 
             AND A.col2 = B.col2
WHERE (B.col3 > 5 OR B.col3 IS NULL)

ok. A lot of stuff...

select * from table_A, table_C left join table_B on A.id=B.id where table_A.id=table_C.id All of a sudden, A.id is no longer a recognized column. I tried changing it so that I have select A.id as foo, and then do on foo=B.id, but foo isn't recognized either. ( Unknown column 'bla' in 'on clause')

This problem of collumn not recognized there is no table or alias named A. You need to put the alias in front of table's name:

select *
from table_A A, table_C
left join table_B on A.id=B.id
where table_A.id=table_C.id

But why are you using join with a comma (,)?
It's better use join statement. It should be something like this:

select * /* any collmn you want */
from tutor_user u
  left join tutor_attends a ON a.userid = u.userid
  left join tutor_tutors_in t ON t.userid = u.userid  
  left join tutor_subject s ON s.subjectid = t.subjectid
  LEFT JOIN tutor_tutor tt on u.userid = tt.userid 

where tutor_attends.schoolid=80 
and tutor_subject.name='Aerospace Studies'

Take a look on 'alias'.
Also you can try the doc: http://dev.mysql.com/doc/refman/5.0/en/select.html

Probably need something like this:

select A.*, B.field1, C.field3 from A
    left join B on A.id=B.id
    left join C on A.id=C.id
    where C.field5 = 'foo'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM