I have three table professor,student and pro_stu where pro_stu contain relationship between professor and student table.
Professor (PID, PNAME).
Student (SID, SNAME).
PRO_STU (PSID, PID, SID).
I want to all student records which student learn from all professor. If you required further information I will give it. I know i have to use join but how to use it I don't know. Thanks.
I want student id=11 which name is hasan which learn by all professor.
I tried following query but no luck
SELECT *
FROM student
INNER JOIN pro_stu ON pro_stu.sid=student.sid
INNER JOIN professor ON professor.pid = pro_stu.pid
SQL Fiddle
I believe here is what you looking for:
SELECT SID, SNAME, count(DISTINCT PID) AS `c` FROM PRO_STU
INNER JOIN Student USING (SID)
GROUP BY SID, SNAME
HAVING `c` = (SELECT count(*) FROM Professor)
Related
I am a little confused with this question. it asks for the following: "Create a single SQL statement that will display all columns from the student and professor tables. You will need to use the student_professor table to set up the joins."
Normally this wouldnt be difficult under the circumstances of just having 2 tables using a related column, but this is asking me to use a 3rd table?
These are the tables
professor, student, student_professor
Columns for 'professor'
ProfessorId, ProfessorProgram, PhoneNo, Age, ProfessorName
Columns for 'student'
studentno, studentprogram, phoneno, age, firstname, lastname
Columns for 'student_professor'
student_professor_id, ProfessorId, StudentNo, Mentor
Not tested, but this should get you started:
SELECT s.*, p.*
FROM professor p, student s, student_professor sp
WHERE sp.professorId = p.proffesorId
AND sp.studentNo = s.studentNo
ORDER BY p.ProfessorName, s.lastname, s.firstname
or
SELECT s.*, p.*
FROM professor p
JOIN student_professor sp ON sp.professorId = p.proffesorId
JOIN student s ON sp.studentNo = s.studentNo
ORDER BY p.ProfessorName, s.lastname, s.firstname
In the above relational schema, how would I do the following?:
List the names of all students that have a higher GPA than the minimum required GPA for the major they have applied for.
A couple of joins should do the trick:
SELECT s.*
FROM Student s
JOIN Apply a ON s.sId = a.sId
JOIN MinimumGPA m on m.major = a.major
WHERE s.gpa > m.mingpa
You use JOIN and NATURAL JOIN(this one is not required but i like it),
with join you ufse 2 tables giving 2 columns that need to be equal(you specify them in the WHERE), NATURAL JOIN does the same but assuming you have 1 or more columns with the same name(those are the ones natural join uses like if they were delared in the where)
So first you fuse MinimumGPA and Apply(they have 2 cols with the same name so natural join)
Select * FROM MinimumGPA NATURAL JOIN Apply
then, since you awhere asked for the NAMES of the students, you fuse that new table(giving it a name, in this case i used MinimumGPAApply, you could name it "the dogtable" if you wanted) with students, since the name on the columns isnt the same you use JOIN and specify the columns in the where, also you add the gpa condition
Select sName from Student JOIN (The first query) As MinimumGPAApply WHERE Student.sId = MinimumGPAApply.sID AND Student.GPA > MinimumGPAApply.minGPA
So at the end you end with somethign like this:
Select sName from Student JOIN (Select * FROM MinimumGPA NATURAL JOIN Apply) As MinimumGPAApply WHERE Student.sId = MinimumGPAApply.sID AND Student.GPA > MinimumGPAApply.minGPA
select s.Cname,s.gpa as studentGpa ,mg.mingpa as mingpaRequired from student s
inner join apply a on s.sid=a.sid
inner join major m on m.major=a.major
inner join minimumGPA mg on mg.major=m.major
where mg.mingpa<s.gpa
i have a table with all the students names and another table with student name and their enrollments in classes i want to show both students with their class names even if they are not enrolled in any classes i used union between the enrolled and not enrolled the only problem that the names are duplicated
Student (student_id, student_name, major, level, age)
Enrolled (student_id, class_name, semester)
and here's the MySQL query:
select student_name,class_name from student natural join enrolled union select student_name,null as class_name from student group by student_name;
Does this work for you?
SELECT
s.student_name,
e.class_name
FROM
student s
LEFT JOIN enrolled e ON s.student_id = e.student_id
GROUP BY student_name;
LEFT JOIN is used when one of the tables can have null values, whilst the other can not. The "left" table (student in this case) is the most important one, the "right" table (enrollment) is the one that can be null.
So it will ALWAYS find the student tables, but when it can't find a class_name that's linked to that student, it just shows up as NULL.
If you want multiple enrollments on the same student, you'll have to remove the group by.
You should use LEFT JOIN like so: SELECT s.student_name, e.class_name from student s LEFT JOIN enrolled e ON s.student_id=e.student_id
What happens actually when we use cascaded join statements
select student.name, count(teacher.id)
from student
left join course on student.course_id = course.id
left join teacher on student.teacher_id = teacher.id
group by student.name;
It seems when I used only the first left join alone it returned 30 rows while using the second left join alone returned 20 rows. But using together returns 600 rows. What is actually happening ? Does the result from the first left join is used in the second ? I don't understand the semantics. Help me understand it.
Since you don't have any join conditions between teacher and course, you're getting a full cross-product between each of the other two joins. Since one join returns 20 rows and the other returns 30 rows, the 3-way join returns 20x30 = 600 rows. Its equivalent to:
SELECT t1.name, count(t2.id)
FROM (SELECT student.name
FROM student
LEFT JOIN course ON student.id = course.id) AS t1
CROSS JOIN
(SELECT teacher.id
FROM student
LEFT JOIN teacher ON student.id = teacher.id) AS t2
GROUP BY t1.name
Notice that the CROSS JOIN of the two subqueries has no ON condition.
The correct way to structure this database is as follows:
student table: id (PK), name
course table: id (PK), name, fee, credits
student_course table: id (PK), student_id (FK), course_id (FK), unique key on (student_id, course_id)
Then to get the name of each student and the average course fee, you would do:
SELECT s.name, AVG(c.fee) AS avg_fee
FROM student AS s
LEFT JOIN student_course AS sc ON s.id = sc.student_id
LEFT JOIN course AS c ON sc.course_id = c.id
All Mysql joins are graphically explained here. Take a look and choose correct joins for both joined tables.
Let's say i have the following model:
Customer(customer_id (PK), firstName, lastName, email)
Item(item_id (PK), name, description)
Orders(orders_id (PK), customer_id (FK), item_id (FK), promotion_id (FK)),
Promotion(promotion_id (PK), date, gift_id (FK))
Gift(gift_id (PK), name, description)
Now, let's say that i have the following requirement:
Retrieve the list of all orders (not grouped by) from all customers and the name column from both the item and gift associated.
The difficult part is that the association table orders has a foreign key column to a one to many table (promotion) that, in his turn, has the foreign key to the gift;
I have the following query that worked, but i figure out that should have a more elegant way to approach the problem than doing a lot of joins like this:
select concat(c.firstName, ' ', c.lastName) as customerName,
i.name, g.name
from customer as c
left join orders as o on c.customer_id = o.customer_id
inner join item as i on o.item_id = i.item_id
inner join promotion as p on o.promotion_id = p.promotion_id
inner join gift as g on p.gift_id = g.gift_id;
How i could resolve the query in a more elegant way?
Thanks in advance!
I think this is perfectly elegant. Joins are very classy and often misunderstood.
You can drop the INNER keywords as joins are inner by default, and the AS keywords are optional; also because your column names are the same across the joins, you can simply use USING instead of ON:
SELECT CONCAT_WS(' ', c.firstName, c.lastName) customerName,
i.name, g.name
FROM customer c
LEFT JOIN orders o USING (customer_id)
JOIN item i USING (item_id)
JOIN promotion p USING (promotion_id)
JOIN gift g USING (gift_id)
Indeed, if those are the only columns having the same name across the joined tables one could go further and use NATURAL joins (although I don't like that as it hides what's going on if the schema changes):
SELECT CONCAT_WS(' ', c.firstName, c.lastName) customerName,
i.name, g.name
FROM customer c
NATURAL LEFT JOIN orders o
NATURAL JOIN item i
NATURAL JOIN promotion p
NATURAL JOIN gift g