SQL problem: 3 tables, requiring JOIN, COUNT, GROUP BY - mysql

I have three (3) tables: Course, Student, Registration. The columns in each table are:
Course: CourseNo, Title, Department, NumberOfCredits, CourseFees
Student: SID, Name, Address, Telephone, Age
Registration: SID, CourseNo, startDate, CompleteDate, Grade
I'm having a hard time figuring out how to write the correct statement that will list the course numbers and titles of courses that have more than 10 students getting a grade lower than 50. I'd like to be able to GROUP BY CourseNo and have a COUNT based on SID.
Any help would be much appreciated, especially if any explanation can be given.
Thanks in advance!

I hope this help
select c.CourseNo, c.Title, count(SID) AS sCount
from Registration r
join Course c on (c.CourseNo = r.CourseNo)
where r.Grade < 50
group by r.CourseNo
HAVING sCount > 10;

Related

How to make a query that may combine COUNT(*) from one and some attributes from the other one

I'm starting to learn some SQL and at the moment I'm having some issues making a query.
I have two tables:
coursetbl: This table has a courseSectionNum, StudentID, courseID, classroom, meetDays, sitNum, beginTime, endTime. I'm interested in courseSectionNum, classroom, meetDays, and both the times for records that have a courseID of 240.
enrolltbl: This table has courseSectionNum, courseID, StudentID, and grade. I'm only interested in records that have 240 as the courseID.
The query must have the columns of interest in coursetbl and a column of the total amount of students enrolled in each section.
I have separately done each one trying to figure out but I can't. This is what I did for each query:
SELECT courseSectionNum
, classroom
, meetDays
, beginTime
, endTime
FROM coursetbl
WHERE courseID = 240;
This next one is for students in each section.
SELECT courseSectionNum
, COUNT(*) AS Total
FROM enrolltbl
WHERE courseID = 240
GROUP BY courseSectionNum;
The issue is that I'm not sure how to combine these two tables to make the query I described above.
Any help will be appreciated. Thank you
I can imagine an update join possibly being along the lines of what you want here:
SELECT
c.courseSectionNum,
c.classroom,
c.meetDays,
c.beginTime,
c.endTime,
COALESCE(e.Total, 0) AS Total
FROM coursetbl c
LEFT JOIN
(
SELECT courseSectionNum, COUNT(*) AS Total
FROM enrolltbl
WHERE courseID = 240
GROUP BY courseSectionNum
) e
ON e.courseSectionNum = c.courseSectionNum
WHERE
c.courseID = 240;

SQL: What country has the most cities?

Hello I started using MySQL and I seem to be having trouble trying to nest formulas. I'm working on a problem and the question is, What country has the most cities?
I have two tables:
CITY:
city
city_id
country_id
COUNTRY:
country
country_id
I am able to join the two tables together to get the cities to match with the countries but after that I don't know how to count to the country that has the most cities.
My current code is:
SELECT city.city, country.country
FROM city, country
WHERE city.country_id = country.country_id
From there I don't know how to add a count function without it coming back as as error. I dont fully understand the basics of nesting.
Thank you, any help is appreciated.
You do not need to do nesting necessarily. To simply know, which country has most number of cities, just use group by:
select country_id, count(1)
from city
group by country_id
This will give you the number of cities in each country. Then you could use a CTE to get the country with the largest number of cities.
You need to GROUP BY if you want to use aggregate functions.
Given the fact that you're very new to this I think you'll get a lot more out of this if you spend a few minutes reading up on some documentation. Don't worry, this is easy stuff so you'll understand this in no time. Please have a look at the following basic info (MySQL GROUP BY basic info) regarding the use of GROUP BY in MySQL. Your questions are answered in the topic regarding 'MySQL GROUP BY with aggregate functions'.
Basic group by:
SELECT
status, COUNT(*)
FROM
orders
GROUP BY status;
Group by using a join:
SELECT
status, SUM(quantityOrdered * priceEach) AS amount
FROM
orders
INNER JOIN
orderdetails USING (orderNumber)
GROUP BY status;
SELECT x.country
FROM country x
JOIN city y
ON y.country_id = x.country_id
GROUP
BY x.country
ORDER
BY COUNT(*) DESC LIMIT 1;
On the (fantastically unlikely) chance that the most civilised countries have equal numbers of cities, you would have to amend this a little.
What makes this difficult is possible ties, i.e. two or more countries sharing the maximum number of cities. As of MySQL 8 you can use window functions to help you with this. Here I compare the country counts and their maximum and then pick the rows were the two match.
select *
from country
where (country_id, true) in -- true means it is a maximum city country
(
select country_id, count(*) = max(count(*)) over()
from city
group by country_id
);
Sorry it was my first post, my code looks terrible.
following my code again.
select
country.country_id,
count(city.city_id)
from
country
inner join
city
on
city.country_id=country.country_id
group by
city.country_id
having
count(city.city_id) =
(SELECT
max(count(city.city_id))
FROM
city
GROUP BY
city.city_id);
Best regards,
Jens
Try the following code:
**select
country.country_id,
count(city.city_id)
from
country
inner join
city
on
city.country_id=country.country_id
group by
city.country_id
having
count(city.city_id) =
(SELECT
max(count(city.city_id))
FROM
city
GROUP BY
city.city_id);**
You need to group by country_id to make sure all cities that are connected to one country_id can be counted.
Where is a good approach, however it does not work together with "group by" as it will be accounted before the "group by" command.
The way you joined your data from different tables is not a very proper yet working way. I suggest to use the inner join in this case to make the command more obvious/better readable.
Count() is used to count the number of cities that accumulate on one country
max() is used to get the country with the most cities (highest count()).
SELECT country_id, count(1)
FROM city
GROUP BY country_id
ORDER BY count(1) desc;
Try following Code -
SELECT *,
(SELECT COUNT(*) FROM cities WHERE cities.country_id=C.country_id) as cities_count
FROM country C
ORDER BY cities_count DESC
LIMIT 0,1
Also is joining the two tables necessary? In your query, you said you need to find What country has the most cities?
Above query will only return one country with max cities.
You can find the country like this:
SELECT MAX(c.id) FROM (SELECT COUNT(id) AS id
FROM city group by country_id) c

Determine total cost per user from 3 Different Tables

I am working on a theatre booking system in MySql (My first SQL project). I have three tables:
Production (contains Title, BasicTicketPrice),
Performance (PerformanceDate, PerformanceTime, Title)
Booking (Email of person who booked, PerformanceDate, PerformanceTime, RowNumber).
Each person booked tickets for two or three performances (using their email to book).
I need to to write a query which will display the prices paid for all booked seats and I need to output the RowNumber, Email of person who booked and the Calculated Price.
I understand that I need to join these tables and make the query display a temporary column called Calculated Price but I don't know how to calculate the price.
I tried this:
SELECT DISTINCT b.RowNumber, b.Email, pr.BasicTicketPrice
FROM booking b, production pr performance p
WHERE p.Title=b.PerfDate*b.PerfTime*b.RowNumber;
SELECT CONCAT (PerfDate, PerfTime, RowNumber) AS BookingID FROM booking;
SELECT RowNumber, Email, CONCAT(PerfDate, PerfTime, RowNumber) AS BookingID FROM booking;
SELECT RowNumber, Email, CONCAT((CONCAT(PerfDate, PerfTime, RowNumber) AS BookingID
FROM booking)BasicTicketPrice*BookingID);
SELECT RowNumber, Email, CONCAT(PerfDate, PerfTime, RowNumber) AS BookingID INTEGER
FROM booking;
SELECT RowNumber FROM booking
LEFT JOIN (SELECT Title FROM performance WHERE '2017-11-01 19:00:00' Email IS NULL);
But it didn't work.
Any suggestions? I will be grateful for any ideas.
Assuming:
One row in Bookings per booked seat
Title to be a suitable primary key for Production
PerformanceDate, PerformanceTime to be a suitable primary composite key for Performance
You'll be looking to join the three tables together as per the keys assumed above. It seems you wish to group the bookings together per performance, by the person booking the tickets - if so, you'll need to use an aggregate to show the seat numbers (I've used GROUP_CONCAT to delimit them), as well as to COUNT the tickets purchased and multiply by the ticket cost.
SELECT
b.Email, prod.Title, per.PerformanceDate, per.PerformanceTime,
GROUP_CONCAT(RowNumber) AS BookedSeats,
COUNT(RowNumber) * prod.BasicTicketPrice AS TotalCost
FROM Booking b
INNER JOIN Performance per
ON b.PerformanceDate = per.PerformanceDate
AND b.PerformanceTime = per.PerformanceTime
INNER JOIN Production prod
ON per.Title = prod.Title
GROUP BY
b.Email, prod.Title, per.PerformanceDate, per.PerformanceTime, prod.BasicTicketPrice
ORDER BY prod.Title, per.PerformanceDate, per.PerformanceTime;
Technically, we should include all non-aggregated columns in the GROUP BY, hence prod.BasicTicketPrice is listed as well.

Need help writing SQL queries(joins, subqueries)

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.

sql query: count the number of subjects enrolled by each student

I have two tables: subject and student.
I'm trying to count the number of subjects enrolled by each student. How do I do that? I'm trying the code below but it doesn't give the answer I need.
SELECT COUNT( subject.SUBJECT ) , student.IDNO, student.FIRSTNAME, subject.SUBJECT
FROM student, subject
GROUP BY subject.SUBJECT
LIMIT 0 , 30
you do have an Enrolment table too, don't you? to resolve the many-to-many relationship between student and subject. you could work with just that. say, your enrolment table has studentID and subjectID columns, then you would only need:
SELECT studentID, COUNT(*) FROM Enrolment GROUP BY studentId;
or, to include their names too,
SELECT s.firstname, COUNT(*) FROM Enrolment e JOIN student s on e.studentId=s.IDNO GROUP BY e.studentId;
You are missing a join condition. Somewhere you are storing info about what subject each student is taking. Perhaps WHERE subject.student_id = student.id.