Sql query to get total number of students in a class - sql

I have this SQL query:
SELECT c.id as ID, c.class_name as CLASS, COUNT(e.student_id) AS STUDENT_COUNT
FROM classes as c
LEFT JOIN enrollments as e on e.class_id = c.id
where c.teacher_id = 8 AND e.approved = 1
group by c.class_name;
What I try to do is to get all the classes and the number of students that have been approved in those classes. The sql query should return something like
ID CLASS STUDENT_COUNT
1 Math 0
2 Biology 2
3 Algebra 1
4 Literature 5
The problem is that because of e.approved = 1 i don't get any classes at all. Suggestions?
My schema is as follows
CLASSES table
id, teacher_id, class_name, grade
ENROLLMENTS table
id, class_id, student_id, approved

Change your query to use the e.approved in the left join condition:
SELECT c.id as ID, c.class_name as CLASS, COUNT(e.student_id) AS STUDENT_COUNT
FROM classes as c
LEFT JOIN enrollments as e on e.class_id = c.id
AND e.approved = 1
where c.teacher_id = 8
group by c.class_name;

Related

ORACLE SQL check if the row number of the table is n, then perform a join

TABLE student: ID, ID2, NAME, AGE
TABLE class: ID, CLASS_NAME, some other columns
TABLE school: ID2, some other columns.
I am trying to perform below in Oracle SQL:
If the count of the records in TABLE "student" with age>5, is 1,
join the student table with "CLASS" table by "ID", else, join the student table with "school" table by "ID2".
I found I cannot put count in where clause. Can someone help?
I would use window functions:
select s.*, . . .
from (select s.*, sum(case when age > 5 then 1 else 0 end) over () as cnt5
from students s
) s left join
class c
on c.id = s.id and cnt5 = 1 left join
school sch
on sch.id2 = s.id2 and cnt5 <> 1
where c.id is not null or sch.id is not null
you can use left join with case
select s.*, case when age > 5 then COALESCE (c.ID,scl.ID2) as id
from student s
left join class c on s.ID=c.ID
left join school scl on s.ID2=scl.ID2
As Gordon said window functions are an option, but this is also a rare occasion where you can deliberately perform a cross join:
select s.*
,...
from students s
left join
(
select count(*) as RECORD_COUNT
from students
where age > 5
) sub
on 1 = 1
left join class c
on s.id = c.id
and sub.record_count = 1
left join school h
on s.id2 = h.id2
and c.id is null

SQL: Which person took which test or not

I want to people and exams they did or did not participate in
I can't figure it out for some reason
Tables
EXAM: ID, NAME, ...etc
PERSON: ID, NAME, ...etc
PERSON_EXAM: ID, PERSON_ID, EXAM_ID, ...etc
Desired result
PERSON_ID EXAM_ID PERSON_EXAM_ID
1 1 1
1 2 NULL
1 3 2
2 1 NULL
2 2 NULL
2 3 3
Currently I did this
select
p.ID as PERSON_ID,
e.ID as EXAM_ID,
(select pe.ID from PERSON_EXAM pe
where pe.PERSON_ID = p.ID and pe.EXAM_ID = e.ID) as PERSON_EXAM_ID
from PERSON p, EXAM e
But I fear it will be slow
I tried to join two tables with one but I can't do that for some reason as
select p.ID as PERSON_ID, e.ID as EXAM_ID, pe.ID as PERSON_EXAM_ID
from PERSON p, EXAM e
left join PERSON_EXAM pe on
p.ID = pe.PERSON_ID and // 'p' isn't recognized because the join is on 'e'
e.ID = pe.ITEM_ID
You have the right idea. Just use the correct syntax. Never use commas in the FROM clause. Always use proper, explicit JOIN syntax:
select p.ID as PERSON_ID, e.ID as EXAM_ID, pe.ID as PERSON_EXAM_ID
from PERSON p cross join
EXAM e left join
PERSON_EXAM pe
on p.ID = pe.PERSON_ID and
e.ID = pe.ITEM_ID;
The semantics of the archaic comma mean that the table alias is not recognized in subsequent on clauses.

Selecting exact value in SQL

I am stuck on a query and decided to ask for help here.
I have 2 tables Students and Values. In students I have the Name and in Values I have the grade.
Let's suppose we have 3 students.
**X** 7,8,10
**Y** 6,9,7
**Z** 7
How can i select the students with the grade EXACTLY "7"?
I tried:
SELECT WHERE grade = 7 But it takes in the consideration the students who have "7" but also other grades too.
I think this problem is tricky, can someone give a hint?
One way is to use a comparison between unconditional and conditional counts:
select s.student_name
from students s join grades g on s.student_id = g.student_id
group by student_id
having count(*) = count(case when g.value = 7 then 1 end)
;
(guessing at some column names along the way)
How it works: After joining the two tables, the rows are grouped by student_id. Then COUNT(*) counts all the grades, and the conditional count counts the grades equal to 7. The query returns the student names when the two counts are equal (meaning all the grades are 7).
Another solution (less efficient):
select s.student_name
from students s inner join grades g on s.student_id = g.student_id
where g.grade = 7
minus
select s.student_name
from students s inner join grades g on s.student_id = g.student_id
where g.grade != 7 or g.grade is null
;
One simple way is to look at the task like this: Find students that have no grade other than seven.
select *
from students
where not exist
(
select *
from grades
where grades.student_id = students.student_id
and grades.grade <> 7
);
or
select *
from students
where student_id not in
(
select student_id
from grades
where grade <> 7
);
I think that an INNER JOIN followed by an exclusive LEFT JOIN would do the trick. Something like this:
WITH
seven AS (
SELECT a.id, a.name, b.grade
FROM student_name a
INNER JOIN student_grade b
ON a.id = b.id
WHERE b.grade = '7'
)
, not_seven AS (
SELECT a.id, a.name, a.grade
FROM seven a
LEFT JOIN student_grade
ON a.id = b.id
WHERE b.id IS NULL
AND b.grade <> '7'
)
SELECT * FROM not_seven;
what about using count and sum? Would that work?
select s.student, Count(v.grade), sum(v.grade)
From student as s
join values as v on v.student = s.student
group by student
having sum(v.grade) = 7 and count(v.grade) = 1

SQL query to find a record which has all matching records in another table

I have below 3 tables and I want to write a SQL query which will list the store present in all city: (here the result should be "Walmart")
Stores:
ID Name
1 Walmart
2 Target
3 Sears
Stores_City
ID Store_id City ID
1 1 10
2 1 20
3 2 10
4 1 30
City
ID Name
10 NewYork
20 Boston
30 Eagan
I am unable to find a query that works. Any help is appreciated!
select s.Name
from Stores s
inner join
(
select store_id, count(distinct city_id)
from stores_city
group by store_id
having count(distinct city_id) = (select count(*) from City)
) x
on x.store_id = s.id;
You can do it by grouping on store_id and checking for the count from stores table.
A straight join would work
Select distinct s.name from stores s inner join store _city SC on s.id=sc.id
Inner join city c on
Sc.city_id = c.id
Here is another way that will work:
select s.*
from stores s
where not exists (
select c.id
from city c
except
select sc.city_id
from stores_city sc
where sc.store_id = s.id
)
Try this:
SELECT
s.Name
FROM Stores s
WHERE NOT EXISTS (SELECT TOP 1
1
FROM City c
LEFT JOIN Stores_City sc
ON c.ID = sc.CityID
AND sc.Store_id = s.ID
WHERE sc.ID IS NULL)

How to count students and classes of every teacher in SQL Server?

Assume 3 tables like this:
Teacher:
teacher_id, name, ...
Student:
student_id, teacher_id, ...
Class:
class_id, teacher_id, ...
Is there a SQL query to get how many students and classes are assigned to every teacher?
Result should be something like this:
teacher_id name students classes
t_001 AAA 3 2
t_002 BBB 1 2
...
Try something like this:
SELECT
t.teacher_id, t.name,
Classes = (SELECT COUNT(*) FROM Class c WHERE c.teacher_id = t.teacher_id),
Students = (SELECT COUNT(*) FROM Student s WHERE s.teacher_id = t.teacher_id)
FROM teacher t
with teacher_students as (
select t.teacher_id,
t.name,
count(s.student_id) as students
from Teacher t
left outer join Student s
on t.teacher_id = s.teacher_id
group by t.teacher_id, t.name
),
teacher_classes as (
select t.teacher_id,
count(c.class_id) as classes
from Teacher t
left outer join Class c
on t.teacher_id = c.teacher_id
group by t.teacher_id
)
select ts.teacher_id,
ts.name,
ts.students,
tc.classes
from teacher_students ts
join teacher_classes tc
on ts.teacher_id = tc.teacher_id
try this:
SELECT T.TEACHER_ID
, T.NAME,
, COUNT(C.TEACHER_ID ) AS CLASSES
, COUNT(S.TEACHER_ID ) AS STUDENTS
FROM TEACHER T
LEFT OUTER JOIN CLASS C
ON T.TEACHER_ID = C.TEACHER_ID
LEFT OUTER JOIN STUDENT S
ON T.TEACHER_ID = S.TEACHER_ID
GROUP BY T.TEACHER_ID, T.NAME