Listing later dates in comparison to another entry in SQL - mysql

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

Related

select student name with profession that apper more the once

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

SQL Query with multiple conditions not working

Okay so this is my best attempt at making a query. It currently executes but returns nothing the other attempts have not worked.
The joins are wrong I believe and I'm not sure how to fix them or do this right
In this query I am trying to get the activity details with staff assigned to those activities matching all conditions below.
The staff and activities are linked in the Allocation table with a Staff ID assigned to an Activity ID there.
--Teach at least 2 modules during 2019 in a certain campus
The staffID must occur at least twice in the Teach table at the field StaffID
The spaID 5 or 6 would correspond to the campus so teach two modules at this time and ID.
--Supervise more than 1 colleagues
This is in the staff table with SupervisorID being a foreign key of StaffID in the same table.
So the Staff ID allocated to the activity needs to supervise more than one colleague with their ID appearing in SupervisorID more than once.
--The related activity is internal one
The activity is internal if it equals to 1.
So to sum it up the activity details should only appear in the query results if it has staff matching all the conditions above
SELECT Activity.AcID, Activity.Title, Activity.CaID, Activity.Internal, Activity.BuID, Budget.Amount FROM Activity
INNER JOIN Budget ON Activity.AcID = Budget.BuID
INNER JOIN Allocation ON Activity.AcID = Allocation.AcID
INNER JOIN Staff ON Allocation.StaffID = Staff.StaffID
INNER JOIN Teach ON Allocation.StaffID = Teach.StaffID
WHERE Activity.Internal=1 AND
Allocation.StaffID IN (
SELECT Staff.SupervisorID
FROM Staff
GROUP BY StaffID
HAVING COUNT(Staff.SupervisorID=Allocation.StaffID) >1)
AND Allocation.StaffID IN (
SELECT Teach.StaffID
FROM Teach
WHERE Teach.Year='2019' AND Teach.SpaID=5 OR 6
GROUP BY Teach.StaffID
HAVING COUNT(Allocation.StaffID=Teach.StaffID) >=2);
Table details are below if you want to look at them for more details
Table Activity -- AcID, Title, CaID, BuID, Status, Started, Ended Internal
Table Allocation -- StaffID, AcID
Table Budget -- BuID, Amount, Approver, Payee, Status
Table Campus -- CaID, Address, GmName, Country, Status
Table Classroom -- RmID, Capacity, CaID, Location, Type, Status
Table Module -- ModuleID, Module Name, DeptID, Programme, TMode, Date_of_Firstoffer
Table SpaceAssign -- SpaID, RmID, TID, Manager, Approved
Table Staff -- StaffID, Title, FirstName, LastName, DeptID, CaID, Joined, LeftD, Current, Salary, ContractType, SupervisorID
Table Teach -- TID, ModuleID, StaffID, SpaID, Semester, Year
I have tried my best to explain this well sorry for any confusion.
Without data It's very tough to find a solution. Please try this:
SELECT Activity.AcID, Activity.Title, Activity.CaID, Activity.Internal, Activity.BuID, Budget.Amount FROM Activity
INNER JOIN Budget ON Activity.AcID = Budget.BuID
INNER JOIN Allocation ON Activity.AcID = Allocation.AcID
INNER JOIN Staff ON Allocation.StaffID = Staff.StaffID
INNER JOIN Teach ON Allocation.StaffID = Teach.StaffID
WHERE Activity.Internal=1 AND
Allocation.StaffID IN (
SELECT Staff.SupervisorID
FROM Staff
GROUP BY SupervisorID
HAVING COUNT(*) >1)
AND Allocation.StaffID IN (
SELECT Teach.StaffID
FROM Teach
WHERE Teach.Year='2019' AND Teach.SpaID=5 OR 6
GROUP BY Teach.StaffID
HAVING COUNT(*) >=2);
It is hard to tell without having access to the data but you can try to change the inner joins to left joins and also:
This
WHERE Teach.Year='2019' AND Teach.SpaID=5 OR 6
Should be
WHERE Teach.Year='2019' AND (Teach.SpaID=5 OR Teach.SpaID=6)
This looks incorrect as well:
INNER JOIN Budget ON Activity.AcID = Budget.BuID
Should be:
INNER JOIN Budget ON Activity.BuID = Budget.BuID

An SQL query to get the exact matching results

In my MySQL database, I have three tables students, classes, courses.
One class has many students.
One class has many courses.
The courses table has one boolean field active, and a string field name.
So overall relationship is (sorry I am not sure how to better illustrate the relationship if it is not clear) :
students (many_to_one) classes (one_to_many) courses
I have a function in Ruby that accepts an array of strings argument for the course names:
def get_student_names_whose_courses_are(active_course_names)
# Run a raw SQL query for the result
end
I would like to write a raw SQL query to get the names of students whose courses (via class) matches exactly the passed in argument course names and are active.
For example, if active_course_names holds values ['foo','bar']. Student-A has active courses 'foo','bar','etc', student-B has active courses 'foo' and 'bar'. The raw quesry should only return student-B, even though student-A also has the two courses active, the point is an exact matching.
What I tried is this:
select stu.name
from students stu
inner join classes clz ON clz.id = stu.class_id
inner join courses cour ON cour.class_id = clz.id AND cour.name in (#{active_course_names,join("','")})
where cour.active = true;
But with this, it returns both student-A and student-B for the example above. How to make the query so that it returns students that have exactly the active courses?
My demo exapmle here
I hope the following answer would be of help to your problem.
If you assign a rank in the same courses (for instance 'FOO'), then you can keep the courses which are repeated in the classes (rank>1) and apply your list of courses. After creating that, you can perform the join to bring the students' information that you need.
SELECT Temp.name,stud.id,stud.name,stud.class_id
FROM (
/*Create a view with the courses which are present with another classroom*/
SELECT T.id, T.name, T.active,T.class_id
FROM (
/*Create a view with only the active courses and their rank*/
SELECT id,name,active,class_id,
#course_rank := IF(#current_course = name,
#course_rank + 1, 1) AS course_rank,
#current_course := name
FROM courses,(select #current_course :=0,#course_rank :=0) r
WHERE active = 1
ORDER BY name, class_id ASC)T
/*Create a filter to bring only the classrooms with the same courses and the selected courses*/
WHERE T.course_rank>1 AND T.name IN ('foo','bar'))Temp
JOIN students stud
ON Temp.class_id=stud.class_id
You can use group_concat like this :
SELECT
stu.name,
GROUP_CONCAT(cour.name ORDER BY cour.name ASC) AS courses
FROM students stu
inner join classes clz ON clz.id = stu.class_id
inner join courses cour ON cour.class_id = clz.id
where
cour.active = true
GROUP BY stu.name
HAVING GROUP_CONCAT(cour.name ORDER BY cour.name ASC) = 'bar,foo'
DEMO IS HERE
Try this:
select distinct student from (
select stu.name student, cour.name course, count(cour.name )
from students stu
inner join classes clz ON clz.id = stu.class_id
inner join courses cour ON cour.class_id = clz.id
where cour.active = true
and cour.name in ('foo','bar')
group by stu.name , cour.name
having count(course) =2) A;
Here is the DEMO
In this DEMO only stu-A needs to be selected.
Number 2 marks that student only has this two courses active and not 3 of them. Hope this is it...

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
;

Using Count in sql

I need help writing a Sql command. I am pretty new at sql so everything is a little confusing.
The problem:
For each instructor list his / her name and the number of students he / she mentors
There are three tables:
Person with the Names and ID
Instructor with Instructor ID which references ID
Student with StudentID and MentorID which references ID
I tried:
select distinct p.Name,count(d.MentorID)
from Person p, Instructor e, Student d
where e.InstructorID = d.MentorID
and p.ID = e.InstructorID;
But that only gives me one results instead a count per instructor.
Build a group and then count() counts for every group and not the complete result.
select p.Name, count(d.MentorID)
from Person p
join Instructor e on p.ID = e.InstructorID
join Student d on e.InstructorID = d.MentorID
group by p.Name