How to add the count from one query into another query - sql

My first query looks like this:
SELECT location, COUNT(*) as sections
FROM section
GROUP BY location
which gives me:

Simply join the queries:
SELECT *
FROM
(
SELECT location, COUNT(*) as sections
FROM section
GROUP BY location
)
FULL OUTER JOIN
(
SELECT s.location, COUNT(*) as students
FROM enrollment e
INNER JOIN section s ON s.section_id = e.section_id
GROUP BY s.location
) USING (location)
ORDER BY location;
Another option is to group the enrollments by section, join and group by location then.
SELECT
location,
COUNT(*) as sections,
SUM(students_in_section) AS students
FROM section s
LEFT JOIN
(
SELECT section_id, COUNT(*) as students_in_section
FROM enrollment
GROUP BY section_id
) e ON e.section_id = s.section_id
GROUP BY s.location
ORDER BY s.location;
Another option is to join the tables and count distinct sections and distinct enrollments.
SELECT
location,
COUNT(DISTINCT s.section_id) as sections,
COUNT(DISTINCT e.enrollment_id) AS students
FROM section s
LEFT JOIN enrollment e ON e.section_id = s.section_id
GROUP BY s.location
ORDER BY s.location;

You can use COUNT(DISTINCT ...) to count the unique sections for each location
SELECT location, COUNT (DISTINCT s.section_id) AS sections, COUNT (*) AS students
FROM enrollment e INNER JOIN section s ON s.section_id = e.section_id
GROUP BY location

Related

What is the alternative for ALL and EVERY in SQLite?

Hey im new to SQL and I'm trying to find the names of students enrolled in the maximum number of classes using SQLite on sqliteonline.com
These are the relations:
This is what I have:
SELECT S.sname
FROM Student S
WHERE S.snum IN (SELECT E.snum
FROM Enrolled E
GROUP BY E.snum
HAVING COUNT (*) >= ALL (SELECT COUNT (*)
FROM Enrolled E2
GROUP BY E2.snum ))
AND this is the error that I get:
I'm guessing the ALL keyword doesn't exist in SQLite or is used differently so I'm wondering what I should do next.
I'm also having the same problem with the EVERY keyword.
What I'm trying to solve:
For each faculty member that has taught classes only in room R128, print the faculty
member's name and the total number of classes she or he has taught.
What I have:
SELECT F.fname, COUNT(*) AS CourseCount
FROM Faculty F, Class C
WHERE F.fid = C.fid
GROUP BY F.fid, F.fname
HAVING EVERY ( C.room = "R128" )
What I get:
You can use ORDER BY and LIMIT:
SELECT S.sname
FROM Student S
WHERE S.snum IN (SELECT E.snum
FROM Enrolled E
GROUP BY E.snum
HAVING COUNT(*) = (SELECT COUNT(*)
FROM Enrolled E2
GROUP BY E2.snum
ORDER BY COUNT(*) DESC
LIMIT 1
)
);
Note: There are other ways to express the query logic. This specifically addresses the question that you asked.
One option uses window functions:
select s.name
from student s
inner join (
select snum, rank() over(order by count(*) desc) rn
from enrolled e
group by snum
) e on e.snum = s.snum
where rn = 1
If your version of SQLite does not support window functions (which were added in version 3.25), I would recommend a join and filtering with a having clause:
select s.name
from students s
inner join enrolled e on e.snum = s.snum
group by s.snum, s.name
having count(*) = (
select count(*)
from enrolled
group by snum
order by count(*) desc limit 1
)

How to find least group of students

I have this tables:
Student - Id, FirstName, LastName, Age
Group - Id, Name
Student_Group - Student_Id, Group_Id
I need to find least group of student. I have tried many times. I would be so glad if somebody helped.
Have you tried to do
SELECT top 1 g.name
FROM group g INNER JOIN Student_group sg ON g.id = sg.Group_Id
WHERE count(sg.student_id) >0
ORDER BY count(sg.student_id)
GROUP BY sg.group_id
?
If you want also the groups with 0 students you should to do
SELECT top 1 g.name
FROM group g INNER JOIN Student_group sg ON g.id = sg.Group_Id
ORDER BY count(sg.student_id)
GROUP BY sg.group_id
--If you just need the group with the least members,
--Group By and Count will work to find the Group with the least members
--Then use select top 1 record and order by GroupCount Ascending
SELECT TOP 1 Group_Id, COUNT(Group_Id) AS [GroupCount]
FROM Student_Group
GROUP BY Group_Id
ORDER BY [GroupCount]

HAVING MAX(COUNT(*)) not working

I have the following code:
SELECT e.Student_ID, s.Name, s.Surname, Result_IS, COUNT(*)
FROM Students s
LEFT JOIN Exams e
ON e.Student_ID=s.Student_ID
WHERE Result_IS='Negative'
GROUP BY e.Student_ID, s.Name, s.Surname, Result_IS
HAVING COUNT(*)=
(
SELECT MAX(COUNT(*)) FROM Exams
WHERE Student_ID=e.Student_ID
AND Result_IS='Negative'
GROUP BY e.Student_ID, s.Name, s.Surname, Result_IS
)
I'm having problem with the HAVING COUNT(*) which should select the row where the COUNT(*) gave the biggest result, but instead it just giving me the output of the first select, which is the following:
I've been trying all sort of things but nothing works to select the row, where count is the maximum.
Just give me a hint please in which direction should I move from here, and what is wrong with the code.
Do
HAVING COUNT(*)=
(
SELECT MAX(COUNT(*)) FROM Exams
WHERE Student_ID=e.Student_ID
AND Result_IS='Negative'
GROUP BY e.Student_ID, s.Name, s.Surname, Result_IS
)
query on the joined table. :)
Why not just order by count(*) desc and select top 1?
SELECT top 1 e.Student_ID, s.Name, s.Surname, Result_IS, COUNT(*) FROM Students s LEFT JOIN Exams e
ON e.Student_ID=s.Student_ID
WHERE Result_IS='Negative'
GROUP BY e.Student_ID, s.Name, s.Surname, Result_IS
order by count(*) desc
I think this is the syntax for Oracle
Select * FROM
(
SELECT e.Student_ID, s.Name, s.Surname, Result_IS, COUNT(*) FROM Students s LEFT JOIN Exams e
ON e.Student_ID=s.Student_ID
WHERE Result_IS='Negative'
GROUP BY e.Student_ID, s.Name, s.Surname, Result_IS
order by count(*) desc
)
Where rownum=1
So, I found out how to do it, the solution is the following:
SELECT e.Student_ID, s.Name, s.Surname, Result_IS, COUNT(*) FROM Students s LEFT JOIN Exams e
ON e.Student_ID=s.Student_ID
WHERE Result_IS='Negative'
GROUP BY e.Student_ID, s.Name, s.Surname, Result_IS
HAVING COUNT(*)=
(
SELECT MAX(count) from
(
SELECT count(*) as count FROM Exams
WHERE Result_Is='Negative'
GROUP BY Student_ID
)
)

SQL group function nested too deeply

I'm trying to create an sql query that will return the smallest occurrence of an id appearing between two tables however I keep getting the error with the line HAVING MIN(COUNT(E.C_SE_ID)). Oracle is saying that the group by function is nested too deeply.
I cannot think of another way of returning C_SE_ID
SELECT CS.C_SE_ID, MIN(COUNT(E.C_SE_ID))
FROM COURSE_SECTION CS, ENROLLMENT E, LOCATION L
WHERE CS.C_SE_ID=E.C_SE_ID
AND CS.LOC_ID=L.LOC_ID
AND L.BLDG_CODE='DBW'
GROUP BY CS.C_SE_ID
HAVING MIN(COUNT(E.C_SE_ID));
in enrollment table s_id and c_se_id are linked, I'm trying to get all the s_id that are related to that c_se_id. with the updated query oracle doesn't like the select * (for obvious reasons) but when I change it too e.c_Se_id I get nothing.
SELECT E.S_ID
FROM COURSE_SECTION CS, ENROLLMENT E
WHERE CS.C_SE_ID=E.C_SE_ID
AND E.C_SE_ID =(
select *
from (select CS.C_SE_ID, count(*) as cnt,
max(count(*)) over (partition by cs.c_se_id) as maxcnt
from COURSE_SECTION CS join
ENROLLMENT E
on CS.C_SE_ID=E.C_SE_ID join
LOCATION L
on CS.LOC_ID=L.LOC_ID
where L.BLDG_CODE='DBW'
GROUP BY CS.C_SE_ID
order by count(*) desc
) t
where cnt = maxcnt);
One way to do this is by nesting your query and then choosing the first row in the output:
select C_SE_ID, cnt
from (select CS.C_SE_ID, count(*) as cnt
from COURSE_SECTION CS join
ENROLLMENT E
on CS.C_SE_ID=E.C_SE_ID join
LOCATION L
on CS.LOC_ID=L.LOC_ID
where L.BLDG_CODE='DBW'
GROUP BY CS.C_SE_ID
order by count(*) desc
) t
where rownum = 1
Note I updated the join syntax to the more modern version using on instead of where.
If you want all minimum values (and there are more than one), then I would use analytic functions. It is a very similar idea to your original query:
select *
from (select CS.C_SE_ID, count(*) as cnt,
max(count(*)) over (partition by cs.c_se_id) as maxcnt
from COURSE_SECTION CS join
ENROLLMENT E
on CS.C_SE_ID=E.C_SE_ID join
LOCATION L
on CS.LOC_ID=L.LOC_ID
where L.BLDG_CODE='DBW'
GROUP BY CS.C_SE_ID
order by count(*) desc
) t
where cnt = maxcnt;
Try this instead of your original query:
SELECT E.S_ID
FROM ENROLLMENT E
where E.C_SE_ID in (select C_SE_ID
from (select CS.C_SE_ID, count(*) as cnt,
max(count(*)) over (partition by cs.c_se_id) as maxcnt
from ENROLLMENT E
LOCATION L
on CS.LOC_ID=L.LOC_ID
where L.BLDG_CODE='DBW'
GROUP BY e.C_SE_ID
) t
where cnt = maxcnt)
);
In addition to fixing the joins, I also removed all references to course_section. This table doesn't seem to be used (unless for filtering results), and removing it implifies the queries.

database sql join question

i have 2 tables called
Location (id, name)
Person (id, name, location_id)
A person has a location Id which joins these tables . . i would like a SQL query that gives me each location and the count of person table for that id.
i could do something like this and then add up the records in code but i want to find out a way that i only get one row per region with count of people in that region
SELECT l.*, r.id from Location l
inner join Person r
on r.location_id = l.id
order by l.name asc
You want to use aggregates and the GROUP BY clause
SELECT l.id, l.name, count(r.id)
FROM Location l
INNER JOIN Person r on r.location_id = l.id
GROUP BY l.id., l.name
ORDER BY l.name asc
Try:
Select L.Name, Count(*) PersonsCount
From Location L
Join Person P On P.Location_Id = L.Id
Group By L.Name
or if you want to see Locations with zero counts,
Select L.Name, Count(*) PersonsCount
From Location L
Left Join Person P On P.Location_Id = L.Id
Group By L.Name
SELECT lo.name, COUNT(*)
FROM LOCATION lo
JOIN PERSON p ON p.location_id = lo.id
GROUP BY lo.name
ORDER BY lo.name
try this
select count(*), Location.name, Location.id from Location, Person where Person.location_id = Location.id group by Location.id