SQL Query From two Table satisfying a condition - mysql

Table 1 name: Student
Name Department
Alex CSE
Bob EEE
Briyan ME
John CSE
James ETE
Mike CE
Table 2 name: Program
Department Semester
CSE Summer
CSE Winter
EEE Summer
ETE Summer
ME Winter
CE Summer
CE Winter
What is the SQL query to print the names and the semester where each student's department have only 1 type of semester? (the server is mysql)
SQL Query Result should be like this:
Name Semester
Bob Summer
Briyan Winter
James Summer
Here, CSE and CE have both summer and winter semester. So Alex, John and Mike are not included.
I have tried this far:
SELECT Student.Name,
Program.Semester
FROM Student
JOIN Program
ON Program.Department = Student.Department
WHERE ....

You could use a In clause on a subquery whetre coubt the department with only a entry
select a.Name, b.Departmnet
from Student a
inner join program b on a.Department = b.Department and b.Department In (
select Department from Program
group by Department having count(*)=1
)

CREATE TABLE #Student(Name NVARCHAR(50),Department NVARCHAR(50))
CREATE TABLE #Program (Department NVARCHAR(50),Semester NVARCHAR(50))
INSERT INTO #Student
SELECT 'Alex','CSE' UNION ALL
SELECT 'Bob','EEE' UNION ALL
SELECT 'Briyan','ME' UNION ALL
SELECT 'John','CSE' UNION ALL
SELECT 'James','ETE' UNION ALL
SELECT 'Mike','CE'
INSERT INTO #Program
SELECT 'CSE','Summer' UNION ALL
SELECT 'CSE','Winter' UNION ALL
SELECT 'EEE','Summer'UNION ALL
SELECT 'ETE','Summer'UNION ALL
SELECT 'ME','Winter'UNION ALL
SELECT 'CE','Summer'UNION ALL
SELECT 'CE','Winter'
;WITH CTE AS (
SELECT Name ,MAX(b.Semester)semester
FROM #Student a INNER JOIN #Program b ON a.Department=b.Department
group by name
having count(distinct semester) = 1
)
SELECT * FROM CTE
GO

You want to join students with single-semester departments. So aggregate your program data by semester to get the single-semester departments. As there is exactly one semester for these departments, you can get the semester with any_value(semester).
select s.name, d.the_semester
from student s
join
(
select any_value(semester) as the_semester
from program
group by department
having count(*) = 1
) d on d.department = s.department
order by s.name;
Another way would be to get all student semester combinations and the group by student to keep only single-semester students.
select s.name, any_value(p.semester) as the_semester
from student s
join program p on p.department = s.department
group by s.name
having count(*) = 1
order by s.name;
Choose whichever query you like better.

You can use aggregation and filter in having clause for those names which have only one semester:
select s.name,
max(p.semester) as semester
from student s
join program p
on s.department = p.department
group by s.name
having count(distinct p.semester) = 1;

Related

mysql select of select

Table Student
StudentID
StudentName
1
A
2
B
3
C
Table Book
BookID
BookName
1
Book1
2
Book2
3
Book3
Table BookAssignment
AssignID
BookID
StudentID
DateTime
1
1
1
2021-06-26
2
2
1
2021-07-01
3
1
2
2021-07-03
The result table should be
StudentID
StudentName
BookCount
1
A
2
2
B
1
3
C
0
How to get the result table in one SQL execution?
Left JOIN seems not an option since it eliminates StudentID 3
Just added another DateTime column to the BookAssignment table - What is SQL syntax to query the book count over the last 7 consecutive days (even for 0 book for day count)?
you need to use simple group by using left join between two tables:
select s.StudentID, s.StudentName , count(*) BookCount
from students s
left join books b
on s.StudentID = b.StudentID
group by s.StudentID, s.StudentName
I'd left join the student table on an aggregate query of the books and use coalesce to fill in the zeros:
SELECT s.StudentID, StudentName, COALESCE(cnt, 0)
FROM student s
LEFT JOIN (SELECT StudentID, COUNT(*) AS cnt
FROM books
GROUP BY StudentID) b ON s.StudentID = b.StudentID
You can also use a correlated subquery:
select s.*,
(select count(*)
from books b
where s.StudentID = b.StudentID
) as bookCount
from students s;
This has some advantages over using a join/group by approach:
You can trivially include all columns in the select. They don't have to repeated in the group by.
With an index on books(StudentID) this often has the best performance.
This avoids the outer aggregation, which can kill performance.
Adding another dimension (say the number of courses the student has) just works, without worrying about Cartesian Products.
select s.StudentID, s.StudentName ,(select count(*) from BookAssignment b where b.studentid = s.studentid) as BookCount
from students s

MySQL subquery with two tables count and group by

I have database of doctors and hospital joined by hospitaldoctor table.
I have to List town, amount of hospitals in each town, but only hospitals which have more than 5 doctors.
SELECT hospital.town, count(town)
FROM hospital
WHERE hospital.id = (
SELECT count(hospital_id)
FROM hospital_doctor GROUP BY hospital_id
HAVING count(hospital_id)>5 )
GROUP BY town
this is my query but MySQL returns me that subquery returns more than 1 row.
HOSPITAL
HOSPITAL DOCTOR
How i should write this query?
You can do what you want with basically the same structure:
Select h.town, count(*)
from hospital h
where h.id in (select hd.hospital_id
from hospital_doctor hd
group by hd.hospital_id
having count(*) > 5
)
group by h.town ;
Note the following:
You want to use in not =, because the subquery could return more than one row.
The subquery should be returning the hospital id not the count.
Use table aliases and qualified column names whenever a table refers to more than one table.
SELECT h.town, count(h.town)
FROM
(
SELECT hospital_id
FROM hospital_doctor GROUP BY hospital_id
HAVING count(doctor_id)>5
) s1
left outer join hospital h on (s1.hospital_id=h.id)
GROUP BY h.town
Select hospital.town, count(town)
from hospital
where
hospital.id in (
select hospital_id
from hospital_doctor
group by hospital_id
having count(hospital_id)>5
)
group by town

Merging tables and getting the output in ascending order

I have two tables as such:
student department
id department_id department_id department_name
5 5 5 Computer Science
1 4 4 Architecture
3 2 1 Mathematics
4 5 3 Chemistry
2 4 2 Physics
I wrote a query as follow and got the following results.
SELECT DEPARTMENTS.DEPT_NAME AS D, STUDENTS.DEPT_ID AS D_ID
FROM STUDENTS
INNER JOIN DEPARTMENTS
ON STUDENTS.DEPT_ID=DEPARTMENTS.DEPT_ID ;
Computer Science 5
Computer Science 5
Physics 2
Architecture 4
Architecture 4
It's fine till here but I want something like
Computer Science 2
Architecture 2
Physics 1
Chemistry 0
Mathematics 0
i.e department name , num_of students where num_of students are in decending order.
What can I add to the query?
I would use COUNT(*) and subquery it for the ORDER BY
SELECT * FROM (
SELECT DEPARTMENTS.DEPT_NAME, COUNT(*) AS num_ofstudents
FROM STUDENTS
LEFT JOIN DEPARTMENTS
ON STUDENTS.DEPT_ID=DEPARTMENTS.DEPT_ID
GROUP BY Departments.Dept_name
) AS a ORDER BY num_ofstudents
edit- Thanks AaronDietz for pointing this out!
You should replace the INNER JOIN with a LEFT JOIN so that the query includes the records from [Departments] that do not have any students. Also, I did not need to include the subquery.
SELECT DEPARTMENTS.DEPT_NAME, COUNT(*) AS num_ofstudents
FROM STUDENTS
LEFT JOIN DEPARTMENTS
ON STUDENTS.DEPT_ID=DEPARTMENTS.DEPT_ID
GROUP BY Departments.Dept_name
ORDER BY num_ofstudents
You can try grouping the departments and the id, then count.
SELECT DEPARTMENTS.DEPT_NAME AS D, COUNT(*) as NID
FROM STUDENTS
INNER JOIN DEPARTMENTS
ON STUDENTS.DEPT_ID=DEPARTMENTS.DEPT_ID
GROUP BY DEPARTMENTS.DEPT_NAME
ORDER BY NID DESC
I think the simplest approach is to select the departments and get the count in a subquery:
select
department_id,
department_name,
(select count(*) from student s where s.department_id = d.department_id) as student_count
from department d
order by 3 desc;
This works well, because you just want one value from the students, namely the count. If you wanted more information then you'd move the subquery to the from clause. E.g.:
select
d.department_id,
d.department_name,
colalesce(s.students, 0) as student_count,
s.ids as student_ids
from department d
left join
(
select
department_id,
count(*) as students,
group_concat(id) as ids
from student
group by department_id
) s on s.department_id = d.department_id
order by 3 desc;
SELECT DEPARTMENTS.DEPT_NAME AS D, count(STUDENTS.DEPT_ID) AS D_ID
FROM STUDENTS
INNER JOIN DEPARTMENTS
ON STUDENTS.DEPT_ID=DEPARTMENTS.DEPT_ID
GROUP BY D
ORDER BY D_ID DESC;
Grouping by department name
Other queries are mostly right but COUNT should be on student id and query should start from department instead of student.
SELECT DEPARTMENTS.DEPT_NAME,
COUNT(id) AS num_ofstudents
FROM DEPARTMENT
LEFT JOIN students ON STUDENTS.DEPT_ID = DEPARTMENTS.DEPT_ID
GROUP BY DEPARTMENTS.DEPT_NAME
ORDER BY num_ofstudents

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