Join query producing 0 results? - sql

I am a bit confused as to how this works, I think I have an idea, but I am not sure. I have two tables:
Student and Classes
The Student table looks like this:
StudentID Name FavoriteClass
The Classes table looks like this:
ClassId ClassName Subject
I have created a relationship between Student.FavoriteClass and Classes.ClassName. However, for the Student table, StudentID is the PK and the ClassId field is the PK for Classes.
I am guessing the reason I can't join these tables is because I am trying to join on fields that aren't keys. If this is the reason, do you guys have recommendations to fix this?
My query looks like this:
SELECT [Classes].[Subject] FROM Classes INNER JOIN Student ON Student.[FavoriteClass].Value = [Classes].[ClassName];
Note: [FavoriteClass].Value is required for Access queries and multi-valued controls.
So if my Student Table had for example:
1 Mark ENG-101
2 Chris CS-103
3 Mary MAT-101
And my Classes Table had like:
1 ENG-101 English
2 CS-103 Computer Science
3 MAT-101 Algebra
4 GS-102 Geography Studies
I want to get the Subject field of Classes where the FavoriteClass of the Student table aligns with the ClassName field of the Classes table.

Please verify that the type of the multi-valued field is really a text type. I guess that it is a number (the ClassId), which would indeed make much more sense. So drop your relationship and (if you will) create a new one between Student.FavoriteClass and Classes.ClassId.
For your query, try this:
SELECT [Student].[Name], [Classes].[Subject]
FROM Classes
INNER JOIN Student ON Student.[FavoriteClass].Value = [Classes].[ClassId];
For more information, I suggest to read this.

Related

SQL Recursive Query | multiple Tables Foreign Keys

Scenario
I have a few tables, each table represents an entity of a unique type. For example lets go with:
School, Subject, Class, Teacher. Listed in order as Parent -> Child
Schema
Each table has:
ID: UUID
Name: CHAR VARYING
{parent}_id: UUID<-- example, class would have Subject_id, or Teacher would have Class_id.
The {parent}_id is the foreign id for each table.
Problem
I want to make a query that lists all the teachers of a given school. In order to do this in this Schema, I need to first query Subject by School_id, then Class by subject_id and then finally teacher by class_id.
A recursive functions makes sense to me but all tutorials I find are doing this within a single table and by ids which don't change with each recursion. In my example, each recursion I will need to search for a different ID.
Question
How do you go about doing this? I could make an array of the ids and make an index, increase index and use that to access the id in the array. This however seems like a common query so I believe there might be a more elegant solution.
Note: I am using PostgreSQL
Edit for Comment
I am using PostgreSQL DB and PGAdmin
Why would UUID not work? It has worked up to this point with no problems; even works with cascading delete using foreign keys.
I can show actual schema. However here is a fictitious layout. Quite straight forward I hope.
School
ID
Name
Subject
ID
Name
School_ID
Class
ID
Name
Subject_ID
Teacher
ID
Name
Class_ID
Expected output
Teacher_ID, Teacher_Name, Class_Name, Subject_Name, School_Name
Something like?:
select
Teacher_ID, Teacher_Name, Class_Name, Subject_Name, School_Name
from
school
join
subject
on
school.id = subject.school_id
join
class
on
class.subject_id = subject.id
join
teacher
on
teacher.class_id = class.id

SQL Server - Question about Inheritance in Database Schemas

I'm having problems understanding the class table inheritance structure that you can implement using database tables. Info on class table inheritance. I have a use case where I have quite different types of persons that I need to model, but they have very minor differences. For example, all of these persons, like Student, Professor and so on, have a surname and a lastname. My first thought was to move theses attributes into a different table inside a base table like you would do in Object Oriented Programming. Here to illustrate further:
Right now, a Professor can only have one person, for example, otherwise it wouldn't make sense in my use case. Also, I have a school table that has two foreign keys, one for the Professor and one for the Student. Lets assume that a school can also have only one professor and one student. This is not the real use case that I have. This example just represents the relation in my real use case which would be too much to explain here.
What I don't understand is how you would collect data based on that. I'm trying to make a SQL Server View where I want to load the Person of the Professor and the Person of the Student from the view point of the School Table. For example:
SELECT
School.professor_id
surname,
lastname
FROM dbo.School AS school
INNER JOIN dbo.Professor as prof
ON school.professor_id = prof.ID
INNER JOIN dbo.Person as prof_person
ON prof.person_id = prof_person.ID
I can output the surname and lastname of the professor, but now I am stuck since I can't figure out how to get the person of the student.
A subtype table typically shares a key with the supertype table, instead of having its own PK and a FK. EG Student.ID is both the PK and the FK.
Then just join Student>Person in addition to Professor>Person, eg
SELECT
School.Id,
prof_person.surname prof_surname,
student_person.surname student_surname
FROM dbo.School AS school
INNER JOIN dbo.Professor as prof
ON school.professor_id = prof.ID
INNER JOIN dbo.Person as prof_person
ON prof.ID = prof_person.ID
INNER JOIN dbo.Student as student
ON school.student_id = student.ID
INNER JOIN dbo.Person as student_person
ON student.ID = student_person.ID
INNER JOIN is associative, so no need for special ordering or parentheses.

How can i get values from under type table to parent type table

Im not sure if i formulated this correctly but i came upon a problem, Basically i made a type of object in SQL Developer HUMAN which contains ID, Name and Surname. I needed a type TEACHER so i made it as an under type of HUMAN with extra attribute. Later on i made a table containing teacher, so i thought all info inserted into teacher, that is the same for human would automatically go into table "all humans" but that didnt work. Is there a way to make some code, where parent object would recieve all information from its under objects?
It sounds like you're looking for something like this:
table Humans
____________
id
name
surname
table Teachers
____________
human_id -- foreign key to Humans table
grade_level
subject -- math, history, etc.
table Students
____________
human_id -- foreign key to Humans table
student_info
Teachers.human_id and Students.human_id are foreign keys that reference Humans.id. To get all teachers, you might do something like this
select *
from Humans inner join Teachers
on Teachers.human_id = Humans.id;
That'll give you a result set with all of the columns from both tables, like
id | name | surname | human_id | grade_level | subject
And you'd do the same to get all the students, replacing Teachers with Students in the above query.

Inner Join Help - How to order table join?

I have 2 tables:
Class (PK = Tutor)
Columns: ID / Tutor / Room
Teacher (PK FK = Tutor)
Columns: Tutor / Contact
I want to join both tables.
Does it matter what order the tables are joined?
ie.
SELECT Class.ID, Class.Tutor, Teacher.Contact
FROM **Class INNER JOIN Teacher** ON Class.Tutor=Teacher.Tutor
or could I do it the other way round and Teacher INNER JOIN Class instead?
Both tables also share a common column name Tutor.
Does it matter if I use Class.Tutor or Teacher.Tutor in the query?
For an INNER JOIN, the order does not matter; the result set you will get will contain all the rows from both Class and Teacher where the common field Tutor matches, whichever order you specify Teacher and Class.
When you use an OUTER JOIN, the order does matter; I would recommend looking at the answers to What is the difference between Left, Right, Outer and Inner Joins?.
Yes, the order matters.
Selecting from class and joining Teacher will show only those classes that have a teacher
Selecting from teacher and joining Class will show only those teachers that have a class
Depending on what you are trying to achieve you'll know which is most relevant.
I'd recommend using "left join" though, it will give you all the classes even if they don't have teacher assigned etc
FWIW "class" is likely to be a reserved word in your database, server side script and client side scripting languages. I'd find another word for that table name.

Weird many to many and one to many relationship

I know I'm gonna get down votes, but I have to make sure if this is logical or not.
I have three tables A, B, C. B is a table used to make a many-many relationship between A and C. But the thing is that A and C are also related directly in a 1-many relationship
A customer added the following requirement:
Obtain the information from the Table B inner joining with A and C, and in the same query relate A and C in a one-many relationship
Something like:
alt text http://img247.imageshack.us/img247/7371/74492374sa4.png
I tried doing the query but always got 0 rows back. The customer insists that I can accomplish the requirement, but I doubt it. Any comments?
PS. I didn't have a more descriptive title, any ideas?
UPDATE:
Thanks to rcar, In some cases this can be logical, in order to have a history of all the classes a student has taken (supposing the student can only take one class at a time)
UPDATE:
There is a table for Contacts, a table with the Information of each Contact, and the Relationship table. To get the information of a Contact I have to make a 1:1 relationship with Information, and each contact can have like and an address book with; this is why the many-many relationship is implemented.
The full idea is to obtain the contact's name and his address book.
Now that I got the customer's idea... I'm having trouble with the query, basically I am trying to use the query that jdecuyper wrote, but as he warns, I get no data back
This is a doable scenario. You can join a table twice in a query, usually assigning it a different alias to keep things straight.
For example:
SELECT s.name AS "student name", c1.className AS "student class", c2.className as "class list"
FROM s
JOIN many_to_many mtm ON s.id_student = mtm.id_student
JOIN c c1 ON s.id_class = c1.id_class
JOIN c c2 ON mtm.id_class = c2.id_class
This will give you a list of all students' names and "hardcoded" classes with all their classes from the many_to_many table.
That said, this schema doesn't make logical sense. From what I can gather, you want students to be able to have multiple classes, so the many_to_many table should be where you'd want to find the classes associated with a student. If the id_class entries used in table s are distinct from those in many_to_many (e.g., if s.id_class refers to, say, homeroom class assignments that only appear in that table while many_to_many.id_class refers to classes for credit and excludes homeroom classes), you're going to be better off splitting c into two tables instead.
If that's not the case, I have a hard time understanding why you'd want one class hardwired to the s table.
EDIT: Just saw your comment that this was a made-up schema to give an example. In other cases, this could be a sensible way to do things. For example, if you wanted to keep track of company locations, you might have a Company table, a Locations table, and a Countries table. The Company table might have a 1-many link to Countries where you would keep track of a company's headquarters country, but a many-to-many link through Locations where you keep track of every place the company has a store.
If you can give real information as to what the schema really represents for your client, it might be easier for us to figure out whether it's logical in this case or not.
Perhaps it's a lack of caffeine, but I can't conceive of a legitimate reason for wanting to do this. In the example you gave, you've got students, classes and a table which relates the two. If you think about what you want the query to do, in plain English, surely it has to be driven by either the student table or the class table. i.e.
select all the classes which are attended by student 1245235
select all the students which attend class 101
Can you explain the requirement better? If not, tell your customer to suck it up. Having a relationship between Students and Classes directly (A and C), seems like pure madness, you've already got table B which does that...
Bear in mind that the one-to-many relationship can be represented through the many-to-many, most simply by adding a field there to indicate the type of relationship. Then you could have one "current" record and any number of "history" ones.
Was the customer "requirement" phrased as given, by the way? I think I'd be looking to redefine my relationship with them if so: they should be telling me "what" they want (ideally what, in business domain language, their problem is) and leaving the "how" to me. If they know exactly how the thing should be implemented, then I'd be inclined to open the source code in an editor and leave them to it!
I'm supposing that s.id_class indicates the student's current class, as opposed to classes she has taken in the past.
The solution shown by rcar works, but it repeats the c1.className on every row.
Here's an alternative that doesn't repeat information and it uses one fewer join. You can use an expression to compare s.id_class to the current c.id_class matched via the mtm table.
SELECT s.name, c.className, (s.id_class = c.id_class) AS is_current
FROM s JOIN many_to_many AS mtm ON (s.id_student = mtm.id_student)
JOIN c ON (c.id_class = mtm.id_class);
So is_current will be 1 (true) on one row, and 0 (false) on all the other rows. Or you can output something more informative using a CASE construct:
SELECT s.name, c.className,
CASE WHEN s.id_class = c.id_class THEN 'current' ELSE 'past' END AS is_current
FROM s JOIN many_to_many AS mtm ON (s.id_student = mtm.id_student)
JOIN c ON (c.id_class = mtm.id_class);
It doesn't seem to make sense. A query like:
SELECT * FROM relAC RAC
INNER JOIN tableA A ON A.id_class = RAC.id_class
INNER JOIN tableC C ON C.id_class = RAC.id_class
WHERE A.id_class = B.id_class
could generate a set of data but inconsistent. Or maybe we are missing some important part of the information about the content and the relationships of those 3 tables.
I personally never heard a requirement from a customer that would sound like:
Obtain the information from the Table
B inner joining with A and C, and in
the same query relate A and C in a
one-many relationship
It looks like that it is what you translated the requirement to.
Could you specify the requirement in plain English, as what results your customer wants to get?