How to use UPDATE and IN in MYSQL? - mysql

I have the tables like this(interconnected by Foreign Keys):
STUDENT:
SNUM, SNAME, FEES
FACULTY:
FID, FNAME
COURSE:
CNAME, TIME, FID
ENROLLED:
SNUM,CNAME
Requirement:
Update FEES of students by 15%, for whom Prof. Kavya is teaching.
I tried the following query, which is not working
UPDATE STUDENT SET FEES=FEES*1.15 WHERE SNUM IN
(
SELECT DISTINCT S.SNUM
FROM STUDENT S, COURSE C, ENROLLED E, FACULTY F
WHERE S.SNUM = E.SNUM AND E.CNAME = C.CNAME
AND C.FID = F.FID
AND F.FNAME = 'KAVYA'
);
Error: You can't specify target table STUDENT for update in FROM clause.
Kindly Help me to solve this problem

In MySQL You cannot update a table and select from the same table in a sub query which has been documented here. You can change the query into join instead of sub query as follows,
UPDATE STUDENT S
JOIN ENROLLED E ON S.SNUM = E.SNUM
JOIN COURSE C ON E.CNAME = C.CNAME
JOIN FACULTY F ON C.FID = F.FID
SET FEES=FEES*1.15
WHERE F.FNAME = 'KAVYA';

It is because in MySQL, you can't update the same table which you have used in the SELECT query. You can change it by joining them instead:
UPDATE STUDENT a
INNER JOIN
(
SELECT DISTINCT S.SNUM
FROM STUDENT S, COURSE C, ENROLLED E, FACULTY F
WHERE S.SNUM = E.SNUM AND E.CNAME = C.CNAME
AND C.FID = F.FID
AND F.FNAME = 'KAVYA'
) b ON a.SNUM = b.SNUM
SET a.FEES = a.FEES * 1.15

Related

Finding duplicate values in mysql when joining two tables

I have the following 3 tables for students and I need to find the names of students who currently are enrolled in classes that meet at the same time
student(**snum**, sname, major, level, age)
class(**cname**, meets_at, room)
enroll(**snum**, **cname**)
The keys for each table is in bold.
I have tried the folling code and I'm not sure whether I'm close to the correct answer here.
select s.sname
from student s
join
( select c.cname
, c.meets_at
, (count(*)
from class c
having count( * ) > 1
) e
on c.cname = e.cname
and s.snum = e.snum;
I would think of this as joining on students with meetsat. So, this gets students with their class times:
select s.sname, c.meets_at
from students s join
enrolls e
on s.snum = e.snum join
classes c
on c.cname = e.cname;
Then, to get the duplicates, use aggregation and filter using having:
select s.snum, s.sname, c.meets_at, count(*) as cnt
from students s join
enrolls e
on s.snum = e.snum join
classes c
on c.cname = e.cname
group by s.snum, sname, c.meets_at
having count(*) >= 2;
Note that this includes the ids as well as the name, because two students could have the same name.
Finally, a student could have multiple pairs of classes that conflict, but you only want to see the student once. Although the above is probably sufficient for your purposes, a more accurate solution for the stated problem would be:
select distinct s.sname
from students s join
enrolls e
on s.snum = e.snum join
classes c
on c.cname = e.cname
group by s.snum, sname, c.meets_at
having count(*) >= 2;
select s.snum, s.sname, c.meets_at ,count(*) as cnt into #tempStudents
from students s
join enrolls e on s.snum = e.snum
join classes c on c.cname = e.cname;
Put the whole data in temporary table
select sname from #tempStudents
group by snum,sname ,meets_at
having cnt >=2
Now apply filtration on temporary table for getting desire data
and if u need distinct name of student put Distinct keyword before sname.

Co-related Nested Query in MySQL

Schema:
Student (snum: integer,
sname: char(30),
major: char(25),
level: char(2),
age: integer)
Faculty (fid: integer,
fname: char(30),
deptid: integer)
Class (cname: char(40),
meets_at: char(20),
room: char(10),
fid: integer | fid REFS Faculty.fid)
Enrolled (snum: integer,
cname: char(40) | snum REFS student.snum,
cname REFS class.name)
Problem:
P1. Find Name of faculty member, department who taught the maximum number of
distinct classes.
P2. Find Names of all classes and their enrollment strength that have enrollment greater than 5.
My Attempt:
#P1:
select distinct f.fname,max(distinct c.cname)
from faculty f,class c
where Exists (select c.fid,max(distinct c.cname) as myCount
from class c where
f.fid=c.fid);
#P2:
select distinct c.cname
from class c
where Exists (select c.cname
from enrolled e where
e.cname=c.cname and count(e.cname)>5);
But this is giving me error. Please help me out.
Q #1: Just do a group by
select f.fname, COUNT(distinct c.cname)
from faculty f
join class c
on f.fid = c.fid
group by f.fname
order by COUNT(distinct c.cname) DESC
limit 1
Using correlated query:
Corraleted v1:
SELECT *
FROM faculty f
WHERE f.id = (SELECT c.fid
FROM class c
GROUP BY c.fid
ORDER BY COUNT(distinct c.cname) DESC
LIMIT 1)
Corraleted v2:
SELECT *
FROM (
SELECT f.*, (SELECT COUNT(distinct c.cname)
FROM class c
WHERE c.fid = f.id) as total
FROM faculty f
) T
ORDER By Total DESC
LIMIT 1
For P2, you can do this with a join, and no nested queries. Doing a condition on an aggregate function is not allowed in the WHERE clause, only in the HAVING clause. You must also group on class names first.
SELECT C.name, count(*) as enrollment
FROM Class C INNER JOIN Enrolled E
ON C.cname=E.cname
GROUP BY C.name
HAVING count(*) > 5;
Doing a co-related nested query, try this:
SELECT C.cname, count(*) as enrollment_count
FROM Class C INNER JOIN Enrolled E
ON C.cname = E.cname
WHERE EXISTS (SELECT *
FROM Enrolled E
WHERE E.cname = C.cname
GROUP BY E.cname
HAVING count(*) > 5)
GROUP BY C.cname;

MySQL :multiple select and join query

I have the following schema :
Department (dept_id, dept_name)
Student (student_id, student_name, major, level, age)
Professor (prof_id, prof_name, dept_id)
Class (name, meets_at, room, prof_id)
Enrolled (student_id, class_name, semester)
I need to Find the names of students with level SR who are enrolled in a class
taught by professor who works in department Computer Science.
based on my relational algebra understanding my attempt was
SELECT s.student_name FROM ( SELECT d.dept_id FROM department as d WHERE d.dept_name = 'computer science'
JOIN professor as p on d.dept_id = p.dept_id
JOIN class as c on p.prof_id = c.prof_id
JOIN enrolled as e on c.name = e.class_name
JOIN student as s on s.student_id = e.student_id )
WHERE s.level = 'sr' ;
but when i try it out i get sql syntax error.
Any help is much appreciated.
SELECT s.student_name
FROM department d
JOIN professor p on d.dept_id = p.dept_id
JOIN class c on p.prof_id = c.prof_id
JOIN enrolled e on c.name = e.class_name
JOIN student s on s.student_id = e.student_id
WHERE s.level = 'sr'
AND d.dept_name = 'computer science'
SELECT s.student_name FROM (you have to mention table name) where s.level = 'sr' ;
without table name it will show error.

How do i write this SQL query for an ALL condition?

I need to build an SQL query in MySQL to solve a problem as part of an assignment for class. I've been working at this problem for awhile, but I'm having a hard time figuring out how to structure this query properly. I'm rather new to the SQL language and databases in general and I'm stumped on this question. I have posted what I've come up with so far, but unfortunately I have not been able to get the results I'm looking for. If anyone could give me some guidance on how to accomplish this I would greatly appreciate it.
Here's what my table structure looks like:
course(cid, fid, room)
enroll(cid, sid, grade)
faculty(fid, fname, dept, rank)
student(sid, sname, major, credits)
Here's the query I need to build:
Show the faculty id and faculty name for all faculty that have taught all computer science majors (major = 'CSC').
Here's what I've tried so far:
select f.fid, f.fname
from faculty f
join course c
on f.fid = c.fid
join enroll e
on c.cid = e.cid
join student s
on e.sid = s.sid
where s.sid = ALL
(select sid
from student
where major = 'CSC');
select f.fid, f.fname
from faculty f
join course c
on f.fid = c.fid
join enroll e
on c.cid = e.cid
join student s
on e.sid = s.sid
group by f.fid, s.sid
having s.sid = ALL
(select sid
from student
where major = 'CSC'));
The logical hurdle I'm having a hard time understanding is how to make sure that the faculty member is teaching ALL of the current CSC majors. You can see that I've tried to add some logic to check each record returned, but I'm afraid I may be misunderstanding the syntax. These queries will run, but they return empty sets. Thanks for the help.
I agree the question may be unclear, and they might just be after all faculty that have taught any CSC major. However, just in case you still need all the faculty that have taught all CSC major, this should work:
The following query tells us the pairs of faculty and CSC majors:
select f.fid, s.sid
from faculty f
inner join course c
on f.fid = c.fid
inner join enroll e
on e.cid = c.cid
inner join student s
on e.sid = s.sid
where s.major = 'CSC'
group by f.fid, s.sid
Therefore, if we know the count of students who are computer science majors:
select count(1)
from student s
where s.major = 'CSC'
Then we can add up the number of CSC majors taught by each faculty member, and check it's equal to the total number of CSC majors:
select b.fid, b.fname
from (
select a.fid, a.fname, count(1) as taught_count
from (
select f.fid, f.fname, s.sid
from faculty f
inner join course c
on f.fid = c.fid
inner join enroll e
on e.cid = c.cid
inner join student s
on e.sid = s.sid
where s.major = 'CSC'
group by f.fid, s.sid
) a
group by a.fid, a.fname
) b
where b.taught_count = (
select count(1)
from student s
where s.major = 'CSC'
)
What you've done looks pretty good. I think you may just be over thinking it. This should logically give you what you're looking for:
Select f.fid, f.fname
from faculty f
join course c on c.fid = f.fid
join enroll e on e.cid = c.cid
join student s on s.sid = e.sid
Where major = 'CSC'
group by f.fid, f.fname
Try with
select f.fid, f.fname
from faculty f
join course c
on f.fid = c.fid
join enroll e
on c.cid = e.cid
join student s
on e.sid = s.sid
where s.sid IN (select sid from student where major = 'CSC');

How to do this sql query?

Schema:
Student(studentid,name,age)
Course(coursename,dept)
enroll(studentid,coursename,grade)
I need to write sql to find student names for each age group with the maximum grade for the courses taken from the history and political science department.
My attempt so far has been
SELECT
name
FROM
student
GROUP BY age
HAVING sid IN
(
SELECT
max(grade)
FROM
enroll e,enroll e1
WHERE
e.studentid = e1.studentid
AND e.coursename = (
SELECT coursename FROM course
WHERE
dname like '%History%'
)
AND e1.coursename = (
SELECT coursename FROM course
WHERE
dname like '%PoliticalScience%'
)
)
You can get the top grade using subquery. Try,
SELECT d.*,
f.dept,
e.grade
FROM student d
INNER JOIN enroll e
on d.studentID = e.studentID
INNER JOIN course f
ON e.courseName = f.courseName
INNER JOIN
(
SELECT a.age, c.dept, Max(b.grade) maxGrade
FROM student a
INNER JOIN enroll b
on a.studentID = b.studentID
INNER JOIN course c
ON b.courseName = c.courseName
WHERE c.dept IN ('history','political science')
GROUP BY a.age, c.dept
) topScore
ON topscore.age = d.age AND
topscore.dept = f.dept AND
topscore.maxGrade = e.grade
You can try something along these lines
select
s.name
from
student s, enroll e,
(
select
s.age as age, e.coursename as coursename, max(e.grade) as grade
from
student s, course c, enroll e
where
s.studentid = e.studentid
and c.coursename = e.coursename
and (c.dept = 'history' or c.dept = 'political science')
group by s.age, e.coursename
) t
where
s.studentid = e.studentid
and s.age = t.age
and e.grade = t.grade
and e.coursename = t.coursename