Schema:
Student (snum: integer,
sname: char(30),
major: char(25),
level: char(2),
age: integer)
Faculty (fid: integer,
fname: char(30),
deptid: integer)
Class (cname: char(40),
meets_at: char(20),
room: char(10),
fid: integer | fid REFS Faculty.fid)
Enrolled (snum: integer,
cname: char(40) | snum REFS student.snum,
cname REFS class.name)
Problem:
P1. Find Name of faculty member, department who taught the maximum number of
distinct classes.
P2. Find Names of all classes and their enrollment strength that have enrollment greater than 5.
My Attempt:
#P1:
select distinct f.fname,max(distinct c.cname)
from faculty f,class c
where Exists (select c.fid,max(distinct c.cname) as myCount
from class c where
f.fid=c.fid);
#P2:
select distinct c.cname
from class c
where Exists (select c.cname
from enrolled e where
e.cname=c.cname and count(e.cname)>5);
But this is giving me error. Please help me out.
Q #1: Just do a group by
select f.fname, COUNT(distinct c.cname)
from faculty f
join class c
on f.fid = c.fid
group by f.fname
order by COUNT(distinct c.cname) DESC
limit 1
Using correlated query:
Corraleted v1:
SELECT *
FROM faculty f
WHERE f.id = (SELECT c.fid
FROM class c
GROUP BY c.fid
ORDER BY COUNT(distinct c.cname) DESC
LIMIT 1)
Corraleted v2:
SELECT *
FROM (
SELECT f.*, (SELECT COUNT(distinct c.cname)
FROM class c
WHERE c.fid = f.id) as total
FROM faculty f
) T
ORDER By Total DESC
LIMIT 1
For P2, you can do this with a join, and no nested queries. Doing a condition on an aggregate function is not allowed in the WHERE clause, only in the HAVING clause. You must also group on class names first.
SELECT C.name, count(*) as enrollment
FROM Class C INNER JOIN Enrolled E
ON C.cname=E.cname
GROUP BY C.name
HAVING count(*) > 5;
Doing a co-related nested query, try this:
SELECT C.cname, count(*) as enrollment_count
FROM Class C INNER JOIN Enrolled E
ON C.cname = E.cname
WHERE EXISTS (SELECT *
FROM Enrolled E
WHERE E.cname = C.cname
GROUP BY E.cname
HAVING count(*) > 5)
GROUP BY C.cname;
Related
I have the following 3 tables for students and I need to find the names of students who currently are enrolled in classes that meet at the same time
student(**snum**, sname, major, level, age)
class(**cname**, meets_at, room)
enroll(**snum**, **cname**)
The keys for each table is in bold.
I have tried the folling code and I'm not sure whether I'm close to the correct answer here.
select s.sname
from student s
join
( select c.cname
, c.meets_at
, (count(*)
from class c
having count( * ) > 1
) e
on c.cname = e.cname
and s.snum = e.snum;
I would think of this as joining on students with meetsat. So, this gets students with their class times:
select s.sname, c.meets_at
from students s join
enrolls e
on s.snum = e.snum join
classes c
on c.cname = e.cname;
Then, to get the duplicates, use aggregation and filter using having:
select s.snum, s.sname, c.meets_at, count(*) as cnt
from students s join
enrolls e
on s.snum = e.snum join
classes c
on c.cname = e.cname
group by s.snum, sname, c.meets_at
having count(*) >= 2;
Note that this includes the ids as well as the name, because two students could have the same name.
Finally, a student could have multiple pairs of classes that conflict, but you only want to see the student once. Although the above is probably sufficient for your purposes, a more accurate solution for the stated problem would be:
select distinct s.sname
from students s join
enrolls e
on s.snum = e.snum join
classes c
on c.cname = e.cname
group by s.snum, sname, c.meets_at
having count(*) >= 2;
select s.snum, s.sname, c.meets_at ,count(*) as cnt into #tempStudents
from students s
join enrolls e on s.snum = e.snum
join classes c on c.cname = e.cname;
Put the whole data in temporary table
select sname from #tempStudents
group by snum,sname ,meets_at
having cnt >=2
Now apply filtration on temporary table for getting desire data
and if u need distinct name of student put Distinct keyword before sname.
I have tried one sql but not working
select cname,avg(salary)
from Company as co,Works as wo
where co.cid=wo.cid and wo.salary > (select avg(salary)
from Company as c,Works as w
where c.cid=w.cid and c.cname='Wipro');
Employee (EID, EName, City)
Works (EID, CID, Salary)
Company (CID, CName, City)
create table Employee(eid int primary key,ename varchar(6),city varchar(6))
create table Works(eid int,cid int primary key,salary int)
create table Company(cid int,cname varchar(6),city varchar(6))
alter table Works add foreign key(eid) references Employee(eid)
alter table Works add foreign key(cid) references Company(cid)
Learn to use proper, explicit, standard JOIN syntax.
That said, you are close. You just need a HAVING clause:
select c.cname, avg(w.salary)
from Company c join
Works w
on c.cid = w.cid
group by c.cname
having avg(w.salary) > (select avg(w2.salary)
from Company c2 join
Works w2
on c2.cid = w2.cid
where c2.cname = 'Wipro'
);
Notes:
Never use commas in the FROM clause.
You should have a GROUP BY when you are using AVG().
Conditions on summarized values should be in the HAVING clause.
SELECT t1.CName,
t2.AvgSalary
FROM Company t1
INNER JOIN (SELECT AVG(Salary) AS AvgSalary,
CID
FROM Works
GROUP BY CID) t2 ON t1.CID = t2.CID
WHERE t2.AvgSalary > (SELECT AVG(Salary)
FROM blog.Works t1a
INNER JOIN blog.Company t2a ON t1a.cid = t2a.cid
WHERE t2a.cname = 'Wipro');
When there's a GROUP BY then you can use the aggregate functions like a SUM in the HAVING clause.
SELECT
co.cname AS company_name,
AVG(wo.salary) AS avg_salary
FROM Company AS co
JOIN Works AS wo ON wo.cid = co.cid
GROUP BY co.cname
HAVING AVG(wo.salary) > (
SELECT AVG(salary)
FROM Company AS c
JOIN Works AS w ON w.cid = c.cid
WHERE c.cname = 'Wipro'
);
You can try it here
I have the tables like this(interconnected by Foreign Keys):
STUDENT:
SNUM, SNAME, FEES
FACULTY:
FID, FNAME
COURSE:
CNAME, TIME, FID
ENROLLED:
SNUM,CNAME
Requirement:
Update FEES of students by 15%, for whom Prof. Kavya is teaching.
I tried the following query, which is not working
UPDATE STUDENT SET FEES=FEES*1.15 WHERE SNUM IN
(
SELECT DISTINCT S.SNUM
FROM STUDENT S, COURSE C, ENROLLED E, FACULTY F
WHERE S.SNUM = E.SNUM AND E.CNAME = C.CNAME
AND C.FID = F.FID
AND F.FNAME = 'KAVYA'
);
Error: You can't specify target table STUDENT for update in FROM clause.
Kindly Help me to solve this problem
In MySQL You cannot update a table and select from the same table in a sub query which has been documented here. You can change the query into join instead of sub query as follows,
UPDATE STUDENT S
JOIN ENROLLED E ON S.SNUM = E.SNUM
JOIN COURSE C ON E.CNAME = C.CNAME
JOIN FACULTY F ON C.FID = F.FID
SET FEES=FEES*1.15
WHERE F.FNAME = 'KAVYA';
It is because in MySQL, you can't update the same table which you have used in the SELECT query. You can change it by joining them instead:
UPDATE STUDENT a
INNER JOIN
(
SELECT DISTINCT S.SNUM
FROM STUDENT S, COURSE C, ENROLLED E, FACULTY F
WHERE S.SNUM = E.SNUM AND E.CNAME = C.CNAME
AND C.FID = F.FID
AND F.FNAME = 'KAVYA'
) b ON a.SNUM = b.SNUM
SET a.FEES = a.FEES * 1.15
I have two tables EMP(id,name,DEPT_id) and DEPT(id ,name). I need to find the department(s) in which the maximum number of employees work. Please help.
This will give the department name of the department which is having maximum number of employees.
Select DEPT_NAME from department where DEPT_ID = (select DEPT_ID from (Select DEPT_ID, count(DEPT_ID) from Employee group by DEPT_ID order by count(DEPT_ID) desc) where rownum = 1);
Just a little more verbose than the other two solutions, but it will get the job done...feel free to tweak to your convenience.
select countbydept.*
from
(
-- from EMP table, let's count number of records per dept
-- and then sort it by count (highest to lowest)
-- and take just the first value. We just care about the highest
-- count
select dept_id, count(*) as counter
from emp
group by dept_id
order by counter desc
limit 1
) as maxcount
inner join
(
-- let's repeat the exercise, but this time let's join
-- EMP and DEPT tables to get a full list of dept and
-- employe count
select
dept.id,
dept.`name`,
count(*) as numberofemployees
from dept
inner join emp on emp.dept_id = dept.id
group by dept.id, dept.`name`
) countbydept
-- combine the two queries's results by matching the employee count
on countbydept.numberofemployees = maxcount.counter
Example: http://sqlfiddle.com/#!9/7d6a2d/1
Try this query.
SELECT a.name,Max(a.NumEmp) AS maxEmpCount FROM ( SELECT d.name,COUNT(*) AS NumEmp FROM EMP e INNER JOIN DEPT d ON e.DEPT_id = d.id GROUP BY e.DEPT_id ) AS a GROUP BY a.name
you can solve this using with statement like this:
with deps as
(select dep.department_name as dep_name, count(emp.employee_id) as cnt
from departments dep
inner join employees emp
on emp.department_id = dep.department_id
group by dep.department_name)
select deps.dep_name,cnt from deps
where cnt=(select max(cnt) from deps)
OR
select dep.department_name as dep_name, count(emp.employee_id) as cnt
from departments dep
inner join employees emp
on emp.department_id = dep.department_id
group by dep.department_name
having count(emp.employee_id) >= all (select count(emp.employee_id) as cnt
from departments dep
inner join employees emp
on emp.department_id =
dep.department_id
group by dep.department_name)
OR
with s1 as
(select dep.department_name as dep_name,
count(emp.employee_id) over(partition by dep.department_name) as cnt
from departments dep
inner join employees emp
on emp.department_id = dep.department_id
order by cnt desc),
s2 as
(select s1.dep_name,
s1.cnt,
row_number() over(order by cnt desc) as row_num
from s1)
select dep_name from s2 where row_num = 1
these solutions are proper for databases like Oracle that we do not have top(1) or limit 1
select Top 1 d.DNAME,count(e.ename) as counts from emp e,dept d where d.DEPTNO=e.DEPTNO
group by d.DNAME
order by counts desc
Or
select d.DNAME,count(e.ename) as counts from emp e,dept d where d.DEPTNO=e.DEPTNO
group by d.DNAME
having count(e.ename) = (select max(micount) from (select count(deptno) micount from emp group by DEPTNO) a)
You can try this query.
Select Id, Name from Dept
Where Id = (Select Top(1) DeptId from Emp
Group By DeptId
order by Count(DeptId) desc)
you can create view to find it.
CREATE VIEW TEMP AS SELECT COUNT(EMP.id) AS A, DEPT.name AS B
FROM EMP JOIN DEPT ON EMP.DEPT_id=DEPT.id GROUP BY DEPT.id;
SELECT MAX(A) FROM TEMP;
Now, EMP(id,name,DEPT_id) and DEPT(id ,name) these two tables are given. Now, I insert some entries in the table in such a manner that:
SELECT COUNT(*) AS NO_OF_EMPLOYEES,
DEPARTMENT.DEPT_NAME
FROM EMP, DEPARTMENT
WHERE EMP.DEPT_ID=DEPARTMENT.DEPT_ID
GROUP BY EMP.DEPT_ID
ORDER BY NO_OF_EMPLOYEES;
This query generates the following:
NO_OF_EMPLOYEES DEPT_NAME
3 Research
3 Finance
4 Sales
4 Product
Now, the query which gives the correct result:
SELECT COUNT(*) AS MAX_NO_OF_EMPLOYEES,
DEPARTMENT.DEPT_NAME
FROM EMP, DEPARTMENT
WHERE EMP.DEPT_ID=DEPARTMENT.DEPT_ID
GROUP BY EMP.DEPT_ID
HAVING MAX_NO_OF_EMPLOYEES=(
SELECT COUNT(*) AS NO_OF_EMPLOYEES
FROM EMP
GROUP BY DEPT_ID
ORDER BY NO_OF_EMPLOYEES DESC
LIMIT 1
);
It will generate:
MAX_NO_OF_EMPLOYEES DEPT_NAME
4 Sales
4 Product
This question can be solved in multiple ways
Using sub query
SELECT name FROM dept WHERE id IN (SELECT dept_id FROM emp HAVING COUNT(dept_id) IN (SELECT MAX(COUNT(dept_id)) FROM emp) GROUP BY dept_id)
Using Join
SELECT name FROM emp e INNER JOIN dept d ON e. dept_id = d. id HAVING COUNT(e.dept_id) IN (SELECT MAX(COUNT(dept_id)) from emp) group by dept_id)
If you have only emp table then below query will hep you get a results -
select a.* from (select deptno, dense_rank() over(order by count(*) desc ) as rank from dbo.emp group by deptno) a where a.rank =1
select deptno,count(*)from emp group by
deptno having count(*)=(select max(count(*))from emp group by deptno);
SELECT department_id, count(employee_id) as 'No_of_Emp'
FROM employees
GROUP BY department_id
ORDER BY No_of_Emp DESC
I am trying to select the classes with maximum enrollment in each department from a table with the following structure:
Courses: cid, dept, name
Enrollment: cid, sid
The idea would be to count all the enrollments in each class, and find the maximum in each department. Unfortunately, I'm having trouble with the maximum-count combination.
My query was going to look something like:
SELECT c.name, MAX(COUNT(*) FROM Enrollment E WHERE E.cid = C.cid)
FROM Courses C
GROUP BY C.dept
But I can't figure out how to get the MAX-COUNT syntax to work properly. I've tried a lot of different examples from Google and StackOverflow and none of them worked for me. MySQL says the syntax is wrong.
I like nested queries for this kind of problem. First select the enrollment counts grouped per class. Then find the max enrollment count grouped per department:
SELECT MAX(cnt) cnt, dept FROM
(
SELECT COUNT(*) cnt, dept, C.cid
FROM Courses C
INNER JOIN Enrollment E on C.cid = E.cid
GROUP BY cid, dept
) a
GROUP BY dept
There is no declaration of E, so you can't use E.cid
So, either you do this
SELECT c.name, COUNT(c.*) as count
FROM Courses C
GROUP BY C.dept
Or,
SELECT c.name, MAX(SELECT COUNT(*) FROM Enrollment E WHERE E.cid = C.cid)
FROM Courses C
GROUP BY C.dept
SELECT MAX(cnt) FROM (
SELECT c.name, COUNT(E.*) AS cnt FROM Enrollment E
INNER JOIN Courses C ON E.cid = C.cid
GROUP BY C.dept
) final