If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

 
Go Back  dBforums > Database Server Software > MySQL > You should generally not have any conditions in the ON part ...

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old 07-23-07, 17:48
darkangel darkangel is offline
Registered User
 
Join Date: Feb 2005
Location: Cape Town, South Africa
Posts: 57
You should generally not have any conditions in the ON part ...

Hi,

From the manual:

Quote:
You should generally not have any conditions in the ON part that are used to restrict which rows you want in the result set, but rather specify these conditions in the WHERE clause. There are exceptions to this rule.
Code:
DROP TABLE IF EXISTS `x`.`members`;
CREATE TABLE  `x`.`members` (
  `acc_num` varchar(9) NOT NULL default '',
  `first_name` varchar(25) NOT NULL default '',
  `last_name` varchar(25) NOT NULL default '',
  `password` varchar(20) NOT NULL default '',
  PRIMARY KEY  (`acc_num`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
The data ...

'A12345', 'Thomas', 'Jackson', 'test'

Code:
DROP TABLE IF EXISTS `x`.`units`;
CREATE TABLE  `x`.`units` (
  `project_id` varchar(5) NOT NULL default '',
  `acc_num` varchar(9) NOT NULL default '',
  `units` mediumint(8) unsigned NOT NULL default '0',
  PRIMARY KEY  (`project_id`,`acc_num`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
The data ...

'SCG01', 'A12345', 42100
'SCG02', 'A12345', 20000

I want the member details, and the units.units if units.project_id exists (otherwise a null column). This is the only thing that I could get working:

Code:
SELECT m.first_name, m.last_name, u.units
FROM members AS m
LEFT JOIN units AS u
ON u.project_id = 'SCG03'
... but, as you can see, the ON clause restricts the result set.

- Is this an exception?
- Is there another method of joining these tables this way?
- Should I just use separate queries?

TIA,

_da.
Reply With Quote
  #2 (permalink)  
Old 07-23-07, 18:27
r937 r937 is offline
SQL Consultant
 
Join Date: Apr 2002
Location: Toronto, Canada
Posts: 19,534
the relevant portion of the excerpt you quoted from the mysql docs is There are exceptions to this rule

this is one situation where you must put the condition into the ON clause

notice that you have forgotten the necessary join condition (shown in blue below) --
Code:
SELECT m.first_name
     , m.last_name
     , u.units
  FROM members AS m
LEFT OUTER
  JOIN units AS u
    ON u.acc_num = m.acc_num
   AND u.project_id = 'SCG03'
compare the results you get from that with the following --
Code:
SELECT m.first_name
     , m.last_name
     , u.units
  FROM members AS m
LEFT OUTER
  JOIN units AS u
    ON u.acc_num = m.acc_num
 WHERE u.project_id = 'SCG03'
see the difference?

__________________
r937.com | rudy.ca
please visit Simply SQL and buy my book
Reply With Quote
  #3 (permalink)  
Old 07-24-07, 08:28
aschk aschk is offline
Registered User
 
Join Date: Mar 2007
Location: 636f6d7075746572
Posts: 770
So as to provide some understanding about what the difference is.

In rudy's improved example:
Code:
LEFT OUTER
  JOIN units AS u
    ON u.acc_num = m.acc_num
   AND u.project_id = 'SCG03'
performs the JOIN on BOTH of the clauses specified. So anything that cohere's in the joining table to BOTH acc_num and project_id = 'SCG03' will be joined.

However, in the first attempt
Code:
LEFT OUTER
  JOIN units AS u
    ON u.acc_num = m.acc_num
 WHERE u.project_id = 'SCG03'
the join is performed ON acc_num ONLY
and then once that set is complete
the WHERE clause is applied to the whole set.

Thus, in the reviewed example the LEFT JOIN ONLY occurs when both the acc_num matches AND the project_id = 'SCG03'. So, if it doesn't match (which is doesn't) it will still return a member.
In the first attempt the LEFT JOIN occurs when both acc_num matches (which is great, it will give results), but then we're testing to see if the project_id = 'SCG03', which there are no joined results for. So we get no results... DOH!

Last edited by aschk; 07-24-07 at 08:33.
Reply With Quote
  #4 (permalink)  
Old 07-24-07, 10:25
darkangel darkangel is offline
Registered User
 
Join Date: Feb 2005
Location: Cape Town, South Africa
Posts: 57
You guys are brilliant!

Rudy, your second example is what I originally used, but of course, as aschk mentioned, the WHERE clause is actually working on the joined table, and not acting as the join condition.

I then moved to my example above, which nearly works (except that I needed to AND the regular join condition), but I wasn't sure if it was acceptable.

2 more basic Qs. if I may:

1) Is the use of the OUTER keyword for compliance to the SQL standard? (i.e. is it best not to omit it.)

2) I realise it makes no difference, but do you think it's best to put the joined table's field first in the join condition, or vice versa?

Thanks SO much for your help.

Regards,

_da.
Reply With Quote
  #5 (permalink)  
Old 07-24-07, 11:12
r937 r937 is offline
SQL Consultant
 
Join Date: Apr 2002
Location: Toronto, Canada
Posts: 19,534
1) OUTER is optional, but i always write it anyway

2) i always put the joined table columns first, it scans better, i.e. it allows you to see easily which table the new table is joining to

compare this --
Code:
  from frabilgimjer
inner
  join quistipunctous
    on frabilgimjer.horbliston = quistipunctous.scrimflabat
inner
  join haplistplogget
    on quistipunctous.whipfintaggle = haplistplogget.opsilfrummer
inner
  join gromulphastic
    on quistipunctous.clapfrepple = gromulphastic.corbustackle
with this --
Code:
  from frabilgimjer
inner
  join quistipunctous
    on quistipunctous.scrimflabat = frabilgimjer.horbliston
inner
  join haplistplogget
    on haplistplogget.opsilfrummer = quistipunctous.whipfintaggle
inner
  join gromulphastic
    on gromulphastic.corbustackle = quistipunctous.clapfrepple
i just think the latter is easier to understand
__________________
r937.com | rudy.ca
please visit Simply SQL and buy my book
Reply With Quote
  #6 (permalink)  
Old 07-24-07, 12:13
guelphdad guelphdad is offline
Registered User
 
Join Date: Mar 2004
Posts: 440
Isn't it corNbustackle?
Reply With Quote
  #7 (permalink)  
Old 07-25-07, 09:51
aschk aschk is offline
Registered User
 
Join Date: Mar 2007
Location: 636f6d7075746572
Posts: 770
In MySQL, there is no difference between LEFT OUTER JOIN and LEFT JOIN, however you may find there IS a different in other database systems.
Reply With Quote
  #8 (permalink)  
Old 07-25-07, 10:05
guelphdad guelphdad is offline
Registered User
 
Join Date: Mar 2004
Posts: 440
Why would there be?
Reply With Quote
  #9 (permalink)  
Old 07-25-07, 10:27
aschk aschk is offline
Registered User
 
Join Date: Mar 2007
Location: 636f6d7075746572
Posts: 770
Apologies i'm being a numpty, LEFT OUTER JOIN is a synonym for LEFT JOIN. For some reason or another I was telling myself these were different.
Reply With Quote
  #10 (permalink)  
Old 07-25-07, 15:00
guelphdad guelphdad is offline
Registered User
 
Join Date: Mar 2004
Posts: 440
I mostly use Mysql, some postgres, I've only dabbled with Oracle and Microsoft Server a wee bit. that's why I was asking.
Reply With Quote
  #11 (permalink)  
Old 07-26-07, 03:07
darkangel darkangel is offline
Registered User
 
Join Date: Feb 2005
Location: Cape Town, South Africa
Posts: 57
Thanks Rudy.

... where on earth do those words come from?
Reply With Quote
  #12 (permalink)  
Old 07-26-07, 03:37
r937 r937 is offline
SQL Consultant
 
Join Date: Apr 2002
Location: Toronto, Canada
Posts: 19,534
they are taken from my virtual database of meaningless names

__________________
r937.com | rudy.ca
please visit Simply SQL and buy my book
Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On