473,767 Members | 7,977 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

how to do joins correctly

Hi,
I'm having trouble doing joins correctly on two tables. I've read up a
lot about the different types of joins and tried lots of variations on
inner, outer, and left joins with no avail. Something isn't correct
with my logic so could anyone give me some pointers on it?

I have 2 tables:

CourseRoster:
ID CourseID StudentID StudentType
01 1000 1000 FT
02 1000 1001 PT
03 1000 1002 FT
04 1000 1003 FT
05 1000 1004 FT
06 1000 1005 FT
07 1000 1006 PT
08 1001 1007 PT
09 1001 1008 FT

CourseExams:
ID ExamID CourseID StudentID Grade
80 2000 1000 1000 95
81 2000 1000 1001 87
82 2000 1000 1002 98
83 2001 1001 1004 74
84 2001 1001 1000 88

How can I set up a query so that I get all students in Course = 1000
and their Grades for ExamID = 2000 are shown even for the students who
do not have one? What I want to get is:

CourseID ExamID StudentID Grade
1000 2000 1000 95
1000 2000 1001 87
1000 2000 1002 98
1000 2000 1003 NULL
1000 2000 1004 NULL
1000 2000 1005 NULL
1000 2000 1006 NULL
Any thoughts and suggestions would be much appreciated.

Justin

Jul 20 '05 #1
6 2084
<jg*****@hotmai l.com> wrote in message
news:11******** *************@f 14g2000cwb.goog legroups.com...
Hi,
I'm having trouble doing joins correctly on two tables. I've read up a
lot about the different types of joins and tried lots of variations on
inner, outer, and left joins with no avail. Something isn't correct
with my logic so could anyone give me some pointers on it?


Things do get complicated fast - don't they?

The way I approach this is with 2 or more simpler queries. Temporary tables
make it simple to do cascading queries.
First I want to isolate the grades for Course=1000, ExamId = 2000

CREATE TEMPORARY TABLE Grades
SELECT StudentID, Grade
FROM CourseExams
WHERE (CourseID=1000) AND (ExamID=2000);

This creates a temporary table of just the grades we are interested in. In
this case, we get (3) grades that qualify from your example data.
Next -
I gather you want to list *all* students taking course 1000 and, *if* they
have a grade for ExamId 2000, you will show that grade. That would mean
taking the CourseRoster of all students enrolled in course 1000 and then
doing a LEFT JOIN with the temporary table of grades you just created.

SELECT 1000 AS CourseID, 2000 AS ExamID, CourseRoster.St udentID,
Grades.Grade
FROM CourseRoster
LEFT JOIN Grades ON CourseRoster.St udentID=Grades. StudentID
WHERE (CourseRoster.C ourseID=1000);

The LEFT JOIN gaurantees that you will see *all* the students, whether they
have a grade or not. LEFT JOIN means you will get a NULL if a grade doesn't
exist for that student. Notice the WHERE clause restricts to only those
students taking CourseID=1000.

I used constant values for CourseID and ExamID in the second query. Our
queries gaurantee that this will be so. Note that, had we drawn the ExamID
from our table join, it would show the ExamID as NULL for those entries
where no entry for that student exists in table CourseExams. Using constants
here is simpler, avoids that problem, and yields exactly the results you
specified.

Now be tidy and do a
DROP TABLE Grades;
Even though the system will drop temporary tables for you as soon as you
disconnect, it pays to be neat and complete.

Cheers!
Thomas Bartkus

Jul 20 '05 #2
jg*****@hotmail .com wrote:
Hi,
I'm having trouble doing joins correctly on two tables. I've read up a
lot about the different types of joins and tried lots of variations on
inner, outer, and left joins with no avail. Something isn't correct
with my logic so could anyone give me some pointers on it?

I have 2 tables:

CourseRoster:
ID CourseID StudentID StudentType
01 1000 1000 FT
02 1000 1001 PT
03 1000 1002 FT
04 1000 1003 FT
05 1000 1004 FT
06 1000 1005 FT
07 1000 1006 PT
08 1001 1007 PT
09 1001 1008 FT

CourseExams:
ID ExamID CourseID StudentID Grade
80 2000 1000 1000 95
81 2000 1000 1001 87
82 2000 1000 1002 98
83 2001 1001 1004 74
84 2001 1001 1000 88

How can I set up a query so that I get all students in Course = 1000
and their Grades for ExamID = 2000 are shown even for the students who
do not have one? What I want to get is:

CourseID ExamID StudentID Grade
1000 2000 1000 95
1000 2000 1001 87
1000 2000 1002 98
1000 2000 1003 NULL
1000 2000 1004 NULL
1000 2000 1005 NULL
1000 2000 1006 NULL
Any thoughts and suggestions would be much appreciated.


You don't have an adequate data model for that query. If there is no
matching row in CourseExams, then the query will return exactly one row
per student. You can't get extra rows for the exams the student hasn't
taken.

You need to add another table:

CourseExamRoste r:
CourseID ExamID
1000 2000
1000 2001
1001 2001

That is, one row per course/exam combination. Then try this query:

SELECT R.CourseID, E.ExamID, S.StudentID, X.Grade
FROM CourseRoster AS R INNER JOIN CourseExamRoste r AS E
ON (R.CourseID = E.CourseID)
LEFT OUTER JOIN CourseExams AS X
ON (R.CourseID = X.CourseID
AND E.ExamID = X.ExamID
AND R.StudentID = X.StudentID)
WHERE R.CourseID = 1000

If you are using MySQL 4.1, you could use a subquery to do a little
trick to form the CourseExamRoste r table on the fly instead of storing
the course/exam combinations:

SELECT R.CourseID, E.ExamID, S.StudentID, X.Grade
FROM CourseRoster AS R INNER JOIN
(SELECT DISTINCT X2.ExamID, X2.CourseID FROM CourseExams X2) AS E
ON (R.CourseID = E.CourseID)
LEFT OUTER JOIN CourseExams AS X
ON (R.CourseID = X.CourseID
AND E.ExamID = X.ExamID
AND R.StudentID = X.StudentID)
WHERE R.CourseID = 1000

But note this will leave out an exam if _none_ of the students took it.
And you might find other cases where it's handy to have a table that
stores the list of course/exams.

Regards,
Bill K.
Jul 20 '05 #3

<jg*****@hotmai l.com> wrote in message
news:11******** *************@f 14g2000cwb.goog legroups.com...
Hi,
I'm having trouble doing joins correctly on two tables. I've read up a
lot about the different types of joins and tried lots of variations on
inner, outer, and left joins with no avail. Something isn't correct
with my logic so could anyone give me some pointers on it?

I have 2 tables:

CourseRoster:
ID CourseID StudentID StudentType
01 1000 1000 FT
02 1000 1001 PT
03 1000 1002 FT
04 1000 1003 FT
05 1000 1004 FT
06 1000 1005 FT
07 1000 1006 PT
08 1001 1007 PT
09 1001 1008 FT

CourseExams:
ID ExamID CourseID StudentID Grade
80 2000 1000 1000 95
81 2000 1000 1001 87
82 2000 1000 1002 98
83 2001 1001 1004 74
84 2001 1001 1000 88

How can I set up a query so that I get all students in Course = 1000
and their Grades for ExamID = 2000 are shown even for the students who
do not have one? What I want to get is:

CourseID ExamID StudentID Grade
1000 2000 1000 95
1000 2000 1001 87
1000 2000 1002 98
1000 2000 1003 NULL
1000 2000 1004 NULL
1000 2000 1005 NULL
1000 2000 1006 NULL
Any thoughts and suggestions would be much appreciated.

Justin


Hi Justin,
I agree with Bill Karwin. Your data model needs some work. For example,
StudentType is best stored in a table called Student rather than with
CourseRoster. The way you have it there is a non-key dependency between
StudentNumber and StudentType which will cause headaches down the road. Get
a good book on data modeling and also learn something about normalization.
But anyway, if you're stuck with the design you have, then this will work:

SELECT DISTINCT t1.CourseID,t1. ExamID,t2.stude ntID,t3.grade FROM CourseExams
AS t1
INNER JOIN CourseRoster as t2 ON t2.CourseID = t1.CourseID
LEFT OUTER JOIN CourseExams as t3 on t3.studentID = t2.StudentID AND
t3.ExamID = t1.ExamID
WHERE T1.CourseID = 1000 AND T1.ExamID = 2000

It's basically creating lookup tables on the fly and then joining them.

Regards
Rich
Jul 20 '05 #4
"Bill Karwin" <bi**@karwin.co m> wrote in message
news:cq******** @enews2.newsguy .com...
jg*****@hotmail .com wrote: <snip> You can't get extra rows for the exams the student hasn't
taken.


Then turn the problem around!

You retrieve *all* the students in the course, regardless of whether they
have a grade for that the exam or not. You can then LEFT JOIN along
StudentID to recover the smaller set of exam grades. No grade means that
student gets Null. But records for all the students get returned.

Thomas Bartkus
Jul 20 '05 #5
Thomas Bartkus wrote:
You retrieve *all* the students in the course, regardless of whether they
have a grade for that the exam or not. You can then LEFT JOIN along
StudentID to recover the smaller set of exam grades. No grade means that
student gets Null. But records for all the students get returned.


Very good suggestion, Thomas! The only small problem is that you can't
take the ExamID from the table; you have to list it as a literal.
Otherwise it'll result in NULLs because of the outer join.

SELECT R.CourseID, '2000' AS ExamID, R.StudentID, X.Grade
FROM CourseRoster AS R LEFT OUTER JOIN CourseExams AS X
ON (R.StudentID = X.StudentID AND R.CourseID = X.CourseID
AND X.ExamID = 2000)
WHERE R.CourseID = 1000

Regards,
Bill K.
Jul 20 '05 #6
On Fri, 31 Dec 2004 02:31:24 -0800, Bill Karwin wrote:
Thomas Bartkus wrote:
You retrieve *all* the students in the course, regardless of whether they
have a grade for that the exam or not. You can then LEFT JOIN along
StudentID to recover the smaller set of exam grades. No grade means that
student gets Null. But records for all the students get returned.


Very good suggestion, Thomas! The only small problem is that you can't
take the ExamID from the table; you have to list it as a literal.
Otherwise it'll result in NULLs because of the outer join.


This is true. You do have to list the ExamID as a literal for the reason
you stated. But this is hardly problematical. The stated conditions are
such that both CourseID and ExamID are constants by design. Under these
circumstances "1000 As CourseID" and "2000 As ExamID" would be perfectly
acceptable.

Apologies for being so nit picky!
Thomas Bartkus

Jul 20 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
514
by: Morten Gulbrandsen | last post by:
Hello, starting from some software database spesification, defined in some Enhanced entity relationship diagram, resulting in all kinds of relationships, 1:1 1:Many Many:1
3
6416
by: Prem | last post by:
Hi, I am having many problems with inner join. my first problem is : 1) I want to know the precedance while evaluating query with multiple joins. eg. select Employees.FirstName, Employees.LastName, TerritoryID, Employees.EmployeeID, RegionID, ProductID from Employees
4
1678
by: H Cohen | last post by:
If a database has relationships establshed between all of the tables via primary and foreign key constraints, why isn't is possible to make a SELECT statement across multiple tables without using a JOIN? If the system knows the relationsip schema already why are JOINS required? Thanks, HC
4
10941
by: GM | last post by:
Does the order in which Joins are peformed (from left to right) matter whether inner or outer when it comes to performance. Assuming that all indexes are the same but the size of the tables is different? For example let's assume we have 5 tables, TABLE1, TABLE2, TABLE3, TABLE4, TABLE5. For example: SELECT Smth from TABLE1 INNER JOIN TABLE2 on Condition1 INNER JOIN TABLE3 on Condition2
4
2048
by: michaelnewport | last post by:
Greetings, I like to write my inner joins as below, but someone at work tells me its not as 'performant' as using the 'inner join' statement. Is this true ? Is there a better way to write it ? thanks
7
31564
by: Steve | last post by:
I have a SQL query I'm invoking via VB6 & ADO 2.8, that requires three "Left Outer Joins" in order to return every transaction for a specific set of criteria. Using three "Left Outer Joins" slows the system down considerably. I've tried creating a temp db, but I can't figure out how to execute two select commands. (It throws the exception "The column prefix 'tempdb' does not match with a table name or alias name used in the query.")
0
1324
by: hotgazpacho | last post by:
I have a query where I need to join several tables, one of which is variable (otherwise I'd just hand-code the query). The main table is called media, and has fields common to all media in my application (like project_id, description, comments, etc). I have another couple of tables, one provides a listing of keywords, and another maps keywords to media. I want to enable a search of media by keyword, allowing for multiple keywords. For a...
7
3056
by: Stephen Poley | last post by:
I have the following situation: - a table of employees, keyed on employee-id; - a table of training sessions, keyed on session-id; - a requirement to log who was present at which session, plus optional extra textual information (e.g. "left early due to illness"). The solution I had in mind was: 1) create a presence table, keyed on employee-id and session-id, containing a 'present' yes/no field and a comment text field; 2) cross-join...
36
2496
by: TC | last post by:
I've used Access for many years. Several times, I've encountered a bug which I refer to as the "Vanishing Joins" bug. When it happens, joins vanish randomly from queries. More specifically, all joins vanish from at least one (seemingly random) query. I've always regarded the Vanishing Joins bug as a symptom of corruption. When it happens, I usually give my users advice on how to recover from corruption, and how to avoid it in the future....
0
10170
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10014
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9960
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9841
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8840
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7384
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5280
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
2
3534
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2808
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.