Courses (cid, cname, description)
Professors (pid, pname)
Teaching (tid, cid, pid, year, semester, department)
Students (sid, lname, fname, b_date, department)
Enrolled_stud (sid, tid, enrollment_date, grade, grade_date)
The Question: query all the students names who have the highest average:
SELECT a.sname,a.avg
FROM (SELECT s1.sname,avg(e.grade)AS avg
FROM Students s1
NATURAL JOIN EnrolledStudents e
GROUP BY s1.sid
) as a
where a.avg=(select max(a.avg))
you can see the results i get in my SQLFIDDLE, and you can see that i was doing something wrong, and i dont get what! it all seem correct to me...
Since it's for study, I'll post this hint first. Think about the where clause - a is the current row. Of course a.avg equals max(a.avg).
Update
Try the following:
SELECT s1.sname, avg(e.grade) AS avg
FROM Students s1
NATURAL JOIN EnrolledStudents e
GROUP BY s1.sid
HAVING avg = (SELECT avg(e.grade) AS avg
FROM EnrolledStudents e
GROUP BY e.sid ORDER BY avg DESC LIMIT 1);
Well if no one has a better looking answer that works, then that makes this the best answer:
SELECT s.sname
FROM Students s
NATURAL JOIN EnrolledStudents e
GROUP BY s.sid
HAVING avg(e.grade) >= ALL(SELECT AVG(e.grade)
FROM EnrolledStudents e
GROUP BY e.sid)
Related
I'm still learning the MySQl.
This is the relational DBMS :
CUSTOMER (CustID, CustName, AnnualRevenue)
TRUCK (TruckNumber, DriverName)
CITY (CityName, Population)
SHIPMENT (ShipmentNumber, CustID, Weight, Year, TruckNumber, CityName)
Now, I have to formulate for these two queries:
Total weight of shipments per year for each city.
Drivers who drove shipments to London but not Paris.
These are the queries i have came up with:
1.
select sum(s.weight), s.year , c.city
from shipment s, city c
INNER JOIN CITY
on s.CityName = c.CityName
You are mixing and old way to JOIN table (which you should avoid because the joining columns are not explicitly stated and it is confusing for others):
FROM shipment s, city c
You should group columns in the select that are not aggregated (year, city). Also it is better to use an alias for the aggregated column (AS total_weight)
select sum(s.weight) AS total_weight, s.year , c.city
from shipment s
INNER JOIN CITY as c
on s.CityName = c.CityName
GROUP BY s.year, c.city
Try to solve the second query and come back if you have a problem.
I need to Find customers who have made a purchase on every type of the flower bouquets offered by the shop. Output schema: (Cust)
Find distinct customers in the database who have not made any order during year 2017. You can compare date values by the standard operators <, >, <=, >=
Output schema: (Cust, CName)
Table Names:
Flowers (Prod, Name, Description, Price)
Customer (Cust, CName, CAddress, CCity, CZip, CState, Card, CardNo, Exp)
Order (Order, Prod, Cust, Date, RName, RAddress, RCity, RZip, RState)
What is the solution for these two queries?
For first query, You can try below -
SELECT C.CName
FROM Customer C
JOIN Order F ON C.CUST = O.CUST
JOIN Flowers F ON F.PROD = O.PROD
GROUP BY O.CUST
HAVING COUNT(DISTINCT PROD) = (SELECT COUNT(DISTINCT PROD) FROM Flowers)
For second query, You can try -
SELECT DISTINCT C.CUST, C.CName
FROM Customer C
WHERE C.CUST NOT EXIST (SELECT 1
FROM Order O
WHERE O.CUST = C.Cust
AND YEAR(Date) = 2017);
So im trying to list the department locations, the project names associated with each department and the number of employees that work on each project.
There is a DeptLocations table(Attributes: Dnum, DLoc)
A Project table(Attributes:PName, Pnum, PLoc, DNum)
An Employee table (Attributes: FNAME, M, LNAME, SSN, BDATE, ADDRESS, S, SALARY, SUPERSSN, DNO)
And a Works_On table (Attributes: ESSN, PNO, HOURS).
This is my SQL query:
select DeptLocations.DLocation, Project.PName, count(ESSN)
from Works_On, DeptLocations, Project, Department
where DeptLocations.DLocation = Project.PLocation and Project.PNumber = Works_On.PNo
For some reason it only yields 1 record, when clearly there should be plenty more. Any help would be awesome.
You need to add group by clause - as you've used aggregated function:
select
DeptLocations.DLocation,
Project.PName,
count(ESSN)
from
Works_On
inner join Project on Project.PNumber = Works_On.PNo
inner join DeptLocations on DeptLocations.DLocation = Project.PLocation
group by
DeptLocations.DLocation, Project.PName
Note: It's better to use explicit join instead of comma separated join.
Given the following schema, I'm supposed to write queries for the questions.
My first query runs but I get no result and the second one gives the subquery returns more than one row error.
student (sid, sname, sex, birthdate, gpa)
prof (pname, dname)
course (cnum, dname, cname)
section (cnum, secnum, pname)
enroll (sid, cnum, secnum, grade)
For each course, return the number of sections (numsections), total number of students enrolled (numstudents), average grade (avggrade), and number of distinct professors who taught the course (numprofs). Only show courses in Chemistry or Computer Science department. Make sure to show courses even if they have no students. Do not show a course if there are no professors teaching that course.
Return the students who received a higher grade than their course section average in at least two courses. Order by number of courses higher than the average and only show top 5.
Sql query:
SELECT C.cnum, C.cname, COUNT(*) AS numsections, COUNT(E.sid) AS numstudents,
AVG(E.grade) AS avggrade, COUNT(P.pname) AS numprofs
FROM course C
JOIN section S ON C.cnum = S.cnum
JOIN enroll E ON C.cnum = E.cnum
JOIN prof P ON S.pname = P.pname
WHERE C.cname = 'Chemistry' OR C.cname = 'Computer Science'
GROUP BY C.cnum, C.cname;`
SELECT S.sid, S.sname
FROM student S
LEFT JOIN enroll E ON S.sid = E.sid
WHERE E.grade > (SELECT AVG(grade)
FROM course C JOIN enroll E2
ON C.cnum = E2.cnum
GROUP BY C.cnum
LIMIT 5);`
About the second query...
Your subquery is getting more than 1 row of data. To use "<" you need yo be sure you are bringing only 1 row and only 1 column.
And if I understand correctly, you only have to show the top 5 students order by the number of times the are better than the average of the course.. I realice this is a learning example so it wont help if I give you the query..
You need to select the top 5 students, but to know that you have to COUNT() the number of times that their GRADE was greater than the AVG() of each course they have taken, at some point in your subquery you sould have the list of students order by the number of times they achive beeing above the average.
So I'm asked to try and convert this statement:
SELECT C.cid, C.cname
FROM Customer C, Buys B
WHERE C.cid = B.cid
GROUP BY C.cid
HAVING count(pid) > 100
to the same thing but not use the HAVING clause. I've been trying to figure it out for the last hour or so but am unsure on how to do this properly. I've been trying to figure out how to use the WHERE clause properly. You can only use the aggregate functions using the HAVING clause correct?
This is what the tables look like
Product(pid, name, price, mfgr)
Buys(cid, pid)
Customer(cid, cname, age)
Simply quoting #zfus answer in comment, just so this question appears to have an answer in the list to avoid further traffic.
SELECT cid, cname
FROM (
SELECT cid, cname, count(*) AS counter
FROM customer c
INNER JOIN buys b on (c.cid=b.cid)
GROUP BY cid, cname
) AS result
WHERE counter > 100