SQL -- Finding students taking 2 or more classes - mysql

I had this question in an interview, and I couldn't quite figure it out. I have three tables: a student table, a classes table and a table linking the other two. Here is a basic schema for them.
STUDENT
student_id | student_name
-----------+-------------
int | varchar(30)
CLASS
class_id | class_name
---------+-----------
int | varchar(30)
ROSTERS
student_id | class_id
-----------+---------
int | int
The rosters table shows which students are taking which classes. How do I write a query showing which students are taking 2 or more classes?

This query will do what you want:
SELECT s.student_name, COUNT(DISTINCT r.class_id) AS num_classes
FROM student s
LEFT JOIN rosters r ON r.student_id = s.student_id
GROUP BY s.student_id
HAVING num_classes >= 2
It counts all the distinct class_id values in roster for each student (num_classes) and returns only students with 2 or more (HAVING num_classes >= 2).
Note I've used a LEFT JOIN to catch all students, however since you want only those with more than 1 class this is not necessary and you could use a straight JOIN.
Also note that it's not necessary to JOIN the class table for this question, however if you wanted the names of the classes the student was taking you would need to.

You can use join, count, having and group by to get the required output:
select r.student_id,s.student_name,count(*)
from STUDENT s inner join ROSTERS r
on s.student_id = r.student_id
group by r.student_id,s.student_name
having count(*)>=2;

You need to join the two tables, STUDENT and ROSTERS (I have used inner join, if required, this can be changed as per requirements), counting the number of classes each student is taking.
SELECT s.student_name,
COUNT(r.class_id) AS count
FROM
STUDENT s
INNER JOIN
ROSTERS r
ON
r.student_id = s.student_id
GROUP BY
s.student_id
HAVING
count >= 2

this will work:
select s.*,r.*,c.*,count(*)
from
student s,
class c,
rosters r where
s.student_id=r.student_id and
c.class_id=r.class_id
group by s.student_id
having count(*)>=2

SELECT COUNT(class_id), student_id
FROM Rosters
GROUP BY student_id
HAVING COUNT(class_id) >=2
This is the simplest way to do it IMO.

Related

Return all courses a student is taking (Many to Many SQL Database example)

I'm fairly new to MySQL, and trying to understand the many-to-many relationship since these examples can popup in interviews
There are 3 tables, and since a Student can have many courses and a Course can have many students, this is a Many-to-Many relationship right?
The tables are
Student- has student ID, name, date of birth, and department.
Courses- Has ID, Name of course
Student_Courses- Has student_id, course_id
How would I display these 2 questions-
1) Given a studentID, return all the names of the courses the student is taking
2) Return the name of students who is taking X amount of courses or more (Ex. 4 or more courses).
Im trying to write queries on these, but I'm stuck...
In the case of selecting all of the courses for a given student ID you could try the following, which will return one row for each Course a Student is associated with.
select
s.name as StudentName,
c.name as CourseName
from `Student` as s
inner join `Student_Course` as sc on (sc.student_id = s.ID)
inner join `Course` as c on (c.ID = sc.course_id)
where
(s.`ID` = 'given_Student_ID_here')
;
As for selecting a list of the names of Students taking N or more courses, for this you might use an aggregating sub-select as a WHERE clause in which we reference one of the outer tables (i.e. [Student]) so that the result of the aggregation is personalised per Student record:
select
s.name as StudentName
from `Student` as s
where
(
(
select count(*)
from `Student_Course` as sc
inner join `Course` as c on (c.ID = sc.course_id)
where (sc.student_id = s.ID)
) >= 4
)
;
You might also consider an alternative approach to this second problem by using the GROUP BY and HAVING clauses:
select
s.name as StudentName
from `Student` as s
inner join `Student_Course` as sc on (sc.student_id = s.ID)
inner join `Course` as c on (c.ID = sc.course_id)
group by
s.name
having
count(*) >= 4
;

Department name and number of students

I found one question in MySQL I am trying. Please tell me if following solution will work or is there any better solution?
select D.DEPT_NAME, COUNT(*)
from Departments D
left outer join STUDENTS S
on S.Dept_ID = D.Dept_ID
group by D.DEPT_NAME
order by 2 desc, 1
Students table has following fields:
Student_ID
Student_Name
Gender
Dept_ID
Departments table has following fields:
Dept_ID
Dept_Name
A university uses 2 data tables, Students and Departments, to store data
about its students and the departments associated with each major.
Write a query to print the respective department name and number of students
majoring in each department for all departments in the Departments table
(even ones with no current students).
Sort your results by descending number of students; if two or more departments have same number of students, then sort those departments alphabetically by department name.
Forgive me altering the formatting of the code.
I would change the ORDER BY, as follows:
SELECT
d.DEPT_NAME,
COUNT(s.STUDENT_ID)
FROM
Departments d
LEFT JOIN Students s ON d.DEPT_ID = s.DEPT_ID
GROUP by
d.DEPT_ID
ORDER by
COUNT(s.STUDENT_ID) DESC,
d.DEPT_NAME ASC
You need a way to count the students in each department, then you need a way to list all departments, even those without students.
Counting the students in each department: (http://sqlfiddle.com/#!15/39a8b/15/0)
SELECT Dept_ID, COUNT(*) Students
FROM STUDENTS
GROUP BY Dept_ID
Then, treating that as a subquery, left join it to your other table. (http://sqlfiddle.com/#!15/39a8b/16/0)
SELECT D.DEPT_NAME, S.Students
FROM Departments D
LEFT JOIN (
SELECT Dept_ID, COUNT(*) Students
FROM STUDENTS
GROUP BY Dept_ID
) S ON D.Dept_ID = S.Dept_ID
The LEFT JOIN preserves rows in the DEPARTMENTS table that don't match the ON clause. This gets you stuff like this.
Biology 7
Mathematics (NULL)
Sociology 11
Physics 3
So you have to deal with that (NULL) problem. Here's how. Change the SELECT to say
SELECT D.DEPT_NAME, IFNULL(S.Students,0)
It's a little tricky to join a table to an aggregate where the aggregate (the COUNT/GROUP BY query) has missing data. But that's how you do it.
You can figure out the ORDER BY stuff on your own.
SELECT d.department_name, COUNT(s.student_name) AS student_count
FROM student s
LEFT JOIN department d
ON s.department_id = d.department_id
GROUP BY department_name
ORDER BY d.department_name;
!!This is finally the correct answer !!
Don't hardcode the problem please stay tuned and work like professional
Excute below.
SELECT
ad.Dept_Name,
count(ass.Student_Id) as Stduent_Enrolled
FROM [Alok.Departments] ad
Left Outer Join [Alok.Students] ass
ON ad.Dept_ID = ass.Dept_ID
Group by ad.Dept_Name
ORDER by
CASE WHEN COUNT(ad.Dept_ID) >=2
THEN ad.DEPT_NAME END desc,
CASE WHEN COUNT(ad.Dept_ID) < 2
THEN ad.DEPT_NAME END asc
1 select department_name, count(student_id) as student_count
2 from student
3 left outer join department ON
4 department.department_id=student.department_id
5 group by department_name
6 order by department_name;
#jaat
Use this query
select count(*) from tblstud_info s,tbldept d where s.dno=d.dno group by d.dname

Complex query consisting 3 tables using mysql

I got 3 tables:
student
internship
student_internship
create table student(student_id varchar(45), student_name varchar(45));
create table internship(internship_id varchar(45), internship_name varchar(45));
and student_intership is the 'bridge' of the two tables.
student_intership(student_id, internship_id)
So, it is a many to many situation.
Situation:
I want to get the name of the internship and number of student, but
if there's no student for that internship, so it should have the following example:
intership_name | count(student_id)
--------------------------------
1. intern1 | 20
2. intern2 | 3
3. intern3 | 0
the code i have tried:
select internship.internship_id, count(student.student_id)
from student_internship, internship, student
where student_internship.student_id = student.student_id
and student_internship.internship_id = internship.internship_id
group by student_internship.internship_id;
Try this:
SELECT i.internship_name, COALESCE(COUNT(si.student_id), 0) AS cnt
FROM internship i
LEFT JOIN student_intership si ON i.internship_id = si.internship_id
GROUP BY si.internship_id, i.internship_name
The above query will return all records of table internship. It will return 0 for internship records having no relation to student records.
Quick stab:
SELECT st.student_id
,st.student_name
,si.InternshipCount
FROM student st
LEFT JOIN (
SELECT count(*) AS InternshipCount
,student_id
FROM student_internship s
INNER JOIN internship i
ON s.student_id = i.student_id
group by student_id
) AS si
ON st.student_id = si.student_id

Getting data from multiple tables using joins

I have various tables like
Student
primary id , students name, course
Papers
paper id, papername, course, semester, type
StudentOptions
primary id, studentid (foreign key - reference student id) and paperid (foreign key - references paper id)
StudentsTerm
studentid (foreign key- references student id) and student semester
Now the kind of result i want is,
I want to choose a course then the term, which will give me the number of papers/subject it has with their types (Mandatory/Optional) and with that i want to have the count of number of students studying those papers from all these tables.
I don't wanna create any view or stuff, Just a normal select query will do.
The query i am running is :
SELECT p_name,
p_id,
type,
Count(sps.studentid) AS counts
FROM students,
str,
papers
LEFT JOIN sps
ON sps.paperid = papers.p_id
WHERE sps.studentid = students.studentid
AND students.studentid = str.studentid
AND sps.studentid = str.studentid
AND str.semesterid = p_semid
AND str.sessionid = 12
AND students.course = c_id
AND c_id = 6
AND p_semid = 1
GROUP BY p_id
As better practice, if you are going to be using explicit JOIN syntax, then don't use implicit syntax. In the query you posted above, you select from papers, but you don't use it anywhere. Also, your column names are slightly ambiguous. If it's easier, alias each table using a single letter, or explicitly prefix the column names. If you're using an aggregate with GROUP BY, you cannot select columns which are not in the group.
Let's assume this is your ER diagram:
Let's first join all the tables:
SELECT a.id, a.name
FROM student a
JOIN str b ON b.student_id = a.id
JOIN sps c ON c.student_id = a.id
JOIN papers d ON d.id = c.paper_id
Now you wish to find the number of students studying papers from a specific course and type:
SELECT a.id, a.name
FROM student a
JOIN str b ON b.student_id = a.id
JOIN sps c ON c.student_id = a.id
JOIN papers d ON d.id = c.paper_id
WHERE b.semester = 12
AND d.course = 6
Because your attributes are ambigiuous, it is hard to tell what tables they are coming from. If you can set up the structure and sample data on SQL Fiddle, we could help you better.

COUNT using two (or more) columns

Is it possible to perform a count based on a combination of two columns?
I have 3 tables:
student:
Student id | Student name | Gender | Dob |
class register: Student id | Class id
Both columns make up the composite primary key.
Classes: Class id | Class name | Class day
I would like to perform a count of the number of students of each gender in each class.
I came up with this query so far:
SELECT class_name AS 'class Name',
Child_gender AS 'Gender',
COUNT(student_id) AS 'Count'
FROM student,classRegister,classes
WHERE student.student_id=classRegister.student_id AND
classRegister.class_id=classes.class_id
GROUP BY class_name,student_gender
ORDER BY class_name;
But it seems to be giving me duplicate results for some of the students.
So, can I modify this query to count the number of instances of a combination of the student_id and class_id?
I'm still very new to MySQL, so I apologise if this is basic for everyone
Try this:
SELECT c.class_name AS 'class Name', s.Child_gender AS 'Gender',
COUNT(s.student_id) AS 'Count'
FROM student s
INNER JOIN classRegister cr ON s.student_id = cr.student_id
INNER JOIN classes c ON cr.class_id = c.class_id
GROUP BY s.Child_gender, s.class_id, c.class_name
ORDER BY c.class_name
SELECT c.class_name AS 'class Name', s.Child_gender AS 'Gender',
COUNT(DISTINCT s.student_id) AS 'Count'
FROM student s
INNER JOIN classRegister cr ON s.student_id = cr.student_id
INNER JOIN classes c ON cr.class_id = c.class_id
GROUP BY c.class_name, s.Child_gender
You might be getting the same student multiple times if they have multiple registrations in classRegister. That sounds gross. The DISTINCT in the COUNT should make sure that they are counted only once per class.