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 > Data Access, Manipulation & Batch Languages > ANSI SQL > Combining LEFT JOIN and MAX

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old 09-23-04, 14:51
akosz akosz is offline
Registered User
 
Join Date: Sep 2004
Posts: 50
Combining LEFT JOIN and MAX

i've got two tables:

table: PEOPLE
columns: ID, NAME

table: TESTS
columns: ID, TEST_NUM, RESULT

rules:
1. one person can have from zero to many tests.
2. i want to see one row for each person, regardless of whether they have any tests or not.
3. i only want to see the most recent (highest numbered) test.

SQL:
i'm able to return all the rows using a LEFT JOIN, but i still need a way to only return the most recent test.

Code:
SELECT     A.ID, A.NAME,
           B.TEST_NUM, B.RESULT
FROM       PEOPLE A
LEFT JOIN  TESTS B
ON         A.ID = B.ID
here's what's in the tables:

Code:
PEOPLE:
ID	NAME
--	----
1	JOE
2	BOB
3	JIM
4	JOHN
5	RALPH
6	STEVE
7	MARY
8	BETH
9	SUE
10	KIM

TESTS:
ID	TEST_NUM	RESULT
--	--------	------
1	1		PASS
1	2		PASS
2	1		FAIL
3	1		FAIL
4	1		PASS
4	2		FAIL
4	3		FAIL
6	1		FAIL
8	1		PASS
9	1		PASS
here's what the query currently returns:

Code:
ID	NAME	TEST_NUM	RESULT
--	----	--------	------
1	JOE	1		PASS
1	JOE	2		PASS
2	BOB	1		FAIL
3	JIM	1		FAIL
4	JOHN	1		PASS
4	JOHN	2		FAIL
4	JOHN	3		FAIL
5	RALPH		
6	STEVE	1		FAIL
7	MARY		
8	BETH	1		PASS
9	SUE	1		PASS
10	KIM
here's what i want it to return:

Code:
ID	NAME	TEST_NUM	RESULT
--	----	--------	------
1	JOE	2		PASS
2	BOB	1		FAIL
3	JIM	1		FAIL
4	JOHN	3		FAIL
5	RALPH		
6	STEVE	1		FAIL
7	MARY		
8	BETH	1		PASS
9	SUE	1		PASS
10	KIM
Reply With Quote
  #2 (permalink)  
Old 09-23-04, 15:14
r937 r937 is offline
SQL Consultant
 
Join Date: Apr 2002
Location: Toronto, Canada
Posts: 19,524
try this --
Code:
select a.id
     , a.name
     , b.test_num
     , b.result
  from people a
left 
  join tests b
    on a.id = b.id
   and b.test_num
     = (select max(test_num)
          from tests
         where id = a.id)
__________________
r937.com | rudy.ca
please visit Simply SQL and buy my book
Reply With Quote
  #3 (permalink)  
Old 09-23-04, 15:21
akosz akosz is offline
Registered User
 
Join Date: Sep 2004
Posts: 50
i get a syntax error with that.

it doesn't tell me why, maybe it doesn't like the 'and' in the 'join'?
Reply With Quote
  #4 (permalink)  
Old 09-23-04, 15:42
r937 r937 is offline
SQL Consultant
 
Join Date: Apr 2002
Location: Toronto, Canada
Posts: 19,524
what is the syntax error?

oh, and perhaps you could also let us know which database you're using
__________________
r937.com | rudy.ca
please visit Simply SQL and buy my book
Reply With Quote
  #5 (permalink)  
Old 09-23-04, 15:45
akosz akosz is offline
Registered User
 
Join Date: Sep 2004
Posts: 50
the real database will be DB2, but i'm testing on a mock access db for the time being. i get the same results in each.

Code:
ODBC Error Code = 37000 (Syntax error or access violation)
[Microsoft][ODBC Microsoft Access Driver] Syntax error. in query expression ''.
i only got this error after i added this:

Code:
and b.test_num
     = (select max(test_num)
          from tests
         where id = a.id)
Reply With Quote
  #6 (permalink)  
Old 09-23-04, 15:49
r937 r937 is offline
SQL Consultant
 
Join Date: Apr 2002
Location: Toronto, Canada
Posts: 19,524
try this --

Code:
    on (
       a.id = b.id
   and b.test_num
     = (select max(test_num)
          from tests
         where id = a.id)
       )
you realize that sql is never portable between different databases, right?
__________________
r937.com | rudy.ca
please visit Simply SQL and buy my book
Reply With Quote
  #7 (permalink)  
Old 09-23-04, 16:03
akosz akosz is offline
Registered User
 
Join Date: Sep 2004
Posts: 50
it's been my experience that basic SQL is portable. it's just the more complicated functions that aren't.

DB2 Error:
Code:
ODBC Error Code = 37000 (Syntax error or access violation)
[StarQuest][StarSQL ODBC Driver]SQL syntax error, .
Access Error:
ODBC Error Code = 37000 (Syntax error or access violation)
[Microsoft][ODBC Microsoft Access Driver] Syntax error. in query expression ' a.id = b.id and b.test_num = (select max(test_num) from tests where id = a.id) '.

it doesn't seem to like those outer parenthesis.
Reply With Quote
  #8 (permalink)  
Old 09-23-04, 16:29
r937 r937 is offline
SQL Consultant
 
Join Date: Apr 2002
Location: Toronto, Canada
Posts: 19,524
Code:
select a.id
     , a.name
     , b.test_num
     , b.result
  from people a
inner 
  join tests b
    on a.id = b.id
 where b.test_num
     = (select max(test_num)
          from tests
         where id = a.id)
union all         
select a.id
     , a.name
     , null
     , null
  from people a
left 
  join tests b
    on a.id = b.id
   and b.id is null
__________________
r937.com | rudy.ca
please visit Simply SQL and buy my book
Reply With Quote
  #9 (permalink)  
Old 09-24-04, 10:16
akosz akosz is offline
Registered User
 
Join Date: Sep 2004
Posts: 50
DB2 doesn't seem to like the nulls.

access had a problem with the join, but who cares about access?

Code:
ODBC Error Code = 42703 ()

[StarQuest][StarSQL ODBC Driver][DB2]NULL IS NOT A COLUMN OF AN INSERTED TABLE, UPDATED TABLE, OR ANY TABLE IDENTIFIED IN A FROM CLAUSE
Reply With Quote
  #10 (permalink)  
Old 09-24-04, 10:23
r937 r937 is offline
SQL Consultant
 
Join Date: Apr 2002
Location: Toronto, Canada
Posts: 19,524
okay, for the second subselect, try:
Code:
select a.id
     , a.name
     , cast(null as integer) as test_num
     , cast(null as char(4)) as result
  from ...
__________________
r937.com | rudy.ca
please visit Simply SQL and buy my book
Reply With Quote
  #11 (permalink)  
Old 09-24-04, 10:36
r937 r937 is offline
SQL Consultant
 
Join Date: Apr 2002
Location: Toronto, Canada
Posts: 19,524
oops, change the and in the last line to where
__________________
r937.com | rudy.ca
please visit Simply SQL and buy my book
Reply With Quote
  #12 (permalink)  
Old 09-24-04, 10:54
akosz akosz is offline
Registered User
 
Join Date: Sep 2004
Posts: 50
hey, i think that worked.

there's no error at least.

some of my test data got purged overnight, so i'm going to repopulate the tables and give it a shot.

i'll post back when i do.

akosz

ps - don't bother with that devshed forum. i cross posted when this first started to see if anybody anywhere had any answers. apparently you do
Reply With Quote
  #13 (permalink)  
Old 09-24-04, 11:42
akosz akosz is offline
Registered User
 
Join Date: Sep 2004
Posts: 50
well that did the trick!

thanks a million for getting me through that one.

the bad news is, it looks like we're allowing duplicate id's in the PEOPLE table. a timestamp will differentiate between them and allow for a primary key. i really don't know how they want me to accomodate for this as it relates to the application i'm developing.

it's going to be a long afternoon...

akosz

btw - there are actually quite a few more columns and tables than what you see here, i just scaled it down to get at the syntax.
Reply With Quote
  #14 (permalink)  
Old 09-27-04, 11:50
akosz akosz is offline
Registered User
 
Join Date: Sep 2004
Posts: 50
now i need to add a WHERE (or an AND) clause to this so that i only get certain matches in the PEOPLE table.

here's the query:

Code:
select a.id
     , a.name
     , b.test_num
     , b.result
  from people a
inner 
  join tests b
    on a.id = b.id
 where b.test_num
     = (select max(test_num)
          from tests
         where id = a.id)
union all         
select a.id
     , a.name
     , cast(null as integer) as test_num
     , cast(null as char(4)) as result
  from people a
left 
  join tests b
    on a.id = b.id
   where b.id is null
here's what i need to add:

Code:
WHERE a.id IN (123,999,343)
i tried adding this as an AND clause after the first WHERE but it only brough back one row instead of 3.
Reply With Quote
  #15 (permalink)  
Old 09-27-04, 11:58
akosz akosz is offline
Registered User
 
Join Date: Sep 2004
Posts: 50
nevermind, i just needed some coffee

it's:

Code:
select a.id
     , a.name
     , b.test_num
     , b.result
  from people a
inner 
  join tests b
    on a.id = b.id
 where b.test_num
     = (select max(test_num)
          from tests
         where id = a.id
         and a.id IN (123,999,343))
union all         
select a.id
     , a.name
     , cast(null as integer) as test_num
     , cast(null as char(4)) as result
  from people a
left 
  join tests b
    on a.id = b.id
   where b.id is null
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