sorry for the question, I'm usually using PostgreSQL but MySQL I can't find my legs In it,
I have this DB :
create table Students (
Student_id int,
Student_name varchar(100)
);
create table Grades
(
student_id numeric,
Profession varchar(10),
Grade numeric
);
insert into Students(Student_id,Student_name) values (1,"avi"),(2,"david"), (3,"mosh"), (4,"adir");
insert into Grades values (2,'math',95), (3,"sport",25), (4,"english",30);
insert into Grades(student_id,Profession) values (1,'math');
I want to get the student name the other profession paper more than once
in this example the output will be:
avi
david
because there both learning math
this is my attempt so far:
select
student_name,
profession
from Students
inner join Grades
on Students.Student_id = Grades.Student_id
group by profession
count(profession) > 1;
this is a link to SQL fiddle
Subquery returns profession wise student count and join with student and grades for retrieving final result where no_of_student per profession appears more than one.
-- Mysql
SELECT s.student_name
FROM Students s
inner join Grades g
on s.Student_id = g.Student_id
inner join (SELECT Profession
, COUNT(1) no_of_std
FROM Grades
GROUP BY Profession) t
on g.Profession = t.Profession
AND t.no_of_std > 1
order by s.student_id
Please check this url https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=a59293c694549e39bcf1678050f6b6f1
N.B.: This query is also applicable for all RDBMS (PostgreSQL, MSSQL, MySQL, ORACLE) because all basics syntax are used here.
Latest version of mysql(v5.8) where analytical function supports and this will also work postgresql, MSSQL etc
SELECT t.student_name
FROM (SELECT s.Student_id, s.student_name
, COUNT(s.Student_id) OVER (PARTITION BY Profession) no_of_std
FROM Students s
inner join Grades g
on s.Student_id = g.Student_id) t
where t.no_of_std > 1
Please check this url https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=f9bced508d1bfc77aacd8b5826aa6a38
For PostgreSQL, please check this url https://dbfiddle.uk/?rdbms=postgres_11&fiddle=1555612e72404eddc820c254c708304a
Related
I have three MySQL tables as below:
CREATE TABLE students (
StudentName VARCHAR(255),
StudentID VARCHAR(255)
);
CREATE TABLE courses (
CourseName VARCHAR(255),
CourseID VARCHAR(255)
);
CREATE TABLE participation (
CourseID VARCHAR(255),
StudentID VARCHAR(255)
);
INSERT INTO students
VALUES ('Biplab', '04CS9501'),
('Amit', '05CS3001'),
('Rahul', '05CS3003'),
('Divya', '05CS3004'),
('Praveen', '05CS3005');
INSERT INTO courses
VALUES ('Business and Science', 'B3D'),
('Economics', 'B3B'),
('Business and Laws', '63O1'),
('Economics and Laws', '63K1'),
('Economics and Science', 'B3E');
INSERT INTO participation
VALUES ('B3D', '04CS9501'),
('B3D', '05CS300'),
('B3D', '05CS3003'),
('B3B', '05CS3003'),
('B3B', '05CS3004'),
('63O1', '04CS9501'),
('63O1', '05CS3004'),
('63K1', '05CS3001'),
('63K1', '05CS3003'),
('63K1', '05CS3004');
Working on the assumption that every student must take a course and every course must have student participation, I would like to test the integrity of the data by being able to identify the courses which do not have students or students that do not have course participation. In this case, student "Praveen" and course "Economics and Science".
How would such a query be constructed?
You can use the following solution to get all courses without participation:
-- to get all empty courses using "WHERE NOT ... IN ..."
SELECT *
FROM courses
WHERE NOT CourseID IN (SELECT CourseID FROM participation)
-- or using "LEFT JOIN"
SELECT c.*
FROM courses c LEFT JOIN participation p ON c.CourseID = p.CourseID
WHERE p.StudentID IS NULL
... and the following solution to get the students without participation:
-- to get all students wihtout participation using "WHERE NOT ... IN ..."
SELECT *
FROM students
WHERE NOT StudentID IN (SELECT StudentID FROM participation)
-- or using "LEFT JOIN"
SELECT s.*
FROM students s LEFT JOIN participation p ON s.StudentID = p.StudentID
WHERE p.CourseID IS NULL
You can also use a LEFT JOIN to get the expected records. Additionaly you can use UNION ALL and a additional column to get all records with one query:
SELECT 'Student' AS type, s.StudentID AS 'ID', s.StudentName AS 'Name'
FROM students s LEFT JOIN participation p ON s.StudentID = p.StudentID
WHERE p.CourseID IS NULL
UNION ALL
SELECT 'Course' AS type, c.CourseID, c.CourseName
FROM courses c LEFT JOIN participation p ON c.CourseID = p.CourseID
WHERE p.StudentID IS NULL
ORDER BY type, Name
demo on dbfiddle.uk
You can use a correlated subquery with NOT EXISTS to check for students with no record in the participation table.
SELECT *
FROM students s
WHERE NOT EXISTS (SELECT *
FROM participation p
WHERE p.studentid = s.studentid);
And analogous for the courses.
I've seen many of such problems, but still do not understand how to do after reviewing the other questions here.
Select s1.email
From student s, student s1
where s1.sname <> 'Alice'
and not exists (select 1
from enrol e, course c, enrol e1
where s.sname = 'Alice'
and s.sid = e.sid
and s1.sid = e1.sid
and e1.code <> e.code );
Please refer to: http://sqlfiddle.com/#!9/aaaf58/5
This is my sample database, added in some dummy values so that i can test out this SQL query.
What i am trying to do is to find the list of students that have taken the exact same courses as this particular student called alice.
Many of the SQL queries that i have seen uses not exists. So i tried to implement it but failed. I should get b#hotmail instead of b#hotmail and c#hotmail. (Since only bob took exactly same course as alice)
Thanks in advance.
Try the following query
SELECT *
FROM
(
SELECT s.sid,s.email,GROUP_CONCAT(e.code ORDER BY code) course_list
FROM student s
JOIN enrol e ON e.sid=s.sid
WHERE s.sname<>'Alice'
GROUP BY s.sid,s.email
) q
WHERE course_list=(
SELECT GROUP_CONCAT(e.code ORDER BY code) course_list
FROM enrol e
JOIN student s ON e.sid=s.sid
WHERE s.sname='Alice'
)
Try this query
select email
from student where sid in
(select distinct sid from enrol where code in
(select distinct code from enrol where sid in
(select sid from student where sname = 'Alice') --In case you have more than one Alice students it still get all classmate of all Alice
)
)
and sname <> 'Alice'
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
;
Table instructor: ID, name, dept_name, salary
Table student: ID, name, dept_name, tot_cred
Table advisor: s_ID, i_ID which contains student id and instructor id for the two table.
I need to find all the instructor and student's name where the department of the advisor is CComp.Sci
I can find all the id of the instructor and student whrer the intructor is fom Computer science. And only the name of the students.
But can't figure out both the name at the same time.
I wrote this:
SELECT student.name
FROM student
WHERE student.ID in (SELECT advisor.s_ID
FROM advisor
, instructor
WHERE advisor.i_ID = instructor.ID
and instructor.dept_name = 'Comp.Sci')
The root solution I think you need here is just a simple join between the three tables. But since you need a single list of both student and instructor names, this complicates things. One option is to union together a query which finds the matching students along with a query which finds the matching instructors.
SELECT s.name, 'student' AS type
FROM student s
INNER JOIN advisor a
ON s.ID = a.s_ID
INNER JOIN instructor i
ON a.i_ID = i.ID
WHERE i.dept_name = 'CComp.Sci'
UNION ALL
SELECT DISTINCT i.name, 'instructor'
FROM student s
INNER JOIN advisor a
ON s.ID = a.s_ID
INNER JOIN instructor i
ON a.i_ID = i.ID
WHERE i.dept_name = 'CComp.Sci'
Using "where .. in (..)" will give you bad performance, also it will not allow you to get the data from the table in the where clause.
Here is a solution if you mean to get the result of instructor name side alone with student name.
SELECT S.name AS Student,I.name AS Instructor
FROM Students AS S
JOIN Advisor AS A ON A.s_ID = S.Id
JOIN Instructor AS I ON I.Id = A.i_ID
WHERE I.dept_name = 'Comp.Sci'
*notice that I used alias
** if you want for example to get all students even those who lack instructor use LEFT JOIN
How would I list the students who started later than start year of student with id = 8871?
This is what I have so far:
SELECT sid s1
FROM Student
WHERE s1.started <= sid = '8871';
I went to this link for some reference but I'm still having issues:
Query comparing dates in SQL
Student Table has:
Student (Lastname, Firstname, SID, Started)
any help would be great
I'd use a self join where one side of the join contains the students you want and the the reference student 8871:
SELECT a.*
FROM student a
JOIN student b ON b.sid = '8871' AND a.started > b.started