I hava the sql as below:
select a.dept, a.name
from students a
group by dept, name
order by dept, name
And get the result:
dept name
-----+---------
CS | Aarthi
CS | Hansan
EE | S.F
EE | Nikke2
I want to summary the num of students for each dept as below:
dept name count
-----+-----------+------
CS | Aarthi | 2
CS | Hansan | 2
EE | S.F | 2
EE | Nikke2 | 2
Math | Joel | 1
How shall I to write the sql?
Although it appears you are not showing all the tables, I can only assume there is another table of actual enrollment per student
select a.Dept, count(*) as TotalStudents
from students a
group by a.Dept
If you want the total count of each department associated with every student (which doesn't make sense), you'll probably have to do it like...
select a.Dept, a.Name, b.TotalStudents
from students a,
( select Dept, count(*) TotalStudents
from students
group by Dept ) b
where a.Dept = b.Dept
My interpretation of your "Name" column is the student's name and not that of the actual instructor of the class hence my sub-select / join. Otherwise, like others, just using the COUNT(*) as a third column was all you needed.
select a.dept, a.name,
(SELECT count(*)
FROM students
WHERE dept = a.dept)
from students a
group by dept, name
order by dept, name
This is a somewhat questionable query, since you get duplicate copies of the department counts. It would be cleaner to fetch the student list and the department counts as separate results. Of course, there may be pragmatic reasons to go the other way, so this isn't an absolute rule.
SELECT dept, name, COUNT(name) as CT from students
group by dept, name
order by dept, name
This should do it (I haven't got any environment to test on at the min)
select a.dept, a.name, count(a.*) as NumOfStudents
from students a
group by dept, name order by dept, name
HTH
Or Otherwise write simply
select dept, name, count(name) as nostud from students group by dept, name order by dept, name
This will give the results requested above
select a.dept, a.name, cnt
from student a
join (
select dept, count(1) as cnt
from student
group by dept
) b on b.dept = a.dept
Related
i have two tables
employee :
employee_number employee_name salary divison_id
division :
division_id division_name
How to Show division id, division name, number of employees working in each division that has the highest number of employees.
I want to have an outcome like this :
division_id division_name total_employee
Z-100 | finance | 3
SELECT *
FROM (SELECT e.division_id,
d.division_name,
Count(1) total_employee
FROM employee e
JOIN division d
ON e.division_id = d.division_id
GROUP BY e.division_id
ORDER BY Count(1) DESC)a
LIMIT 1
If you want all the department with most employees you should consider that more than one department can have that. So I am revising my answer and instead of top I am using Rank() with CTE to get all the divisions with most number of employees.
with DivisionWithMostEmployee as
(
select Rank()over(order by count(*) desc) RowNumber, d.division_id, d.division_name, count(*) TotalEmployee
from division d, employee e where d.division_id=e.division_id
group by d.division_id,d.division_name
)
select Division_id,Division_name,TotalEmployee from DivisionWithMostEmployee where RowNumber=1
I wrote a query joining two tables and I got a below resultset:
SELECT emp.employee_id,
dept.department_name,
dept.department_id
FROM employee emp,
department dept
WHERE emp.department_id = dept.department_id;
Employee_ID Department Department_ID
Mark Sales D1
Mark Marketing D2
Justin Textiles D3
Kimberley (null) (null)
However, I need to display below output with one new field called 'Status'.Mark can work in both the departments and so the count is "2" and the status will be 'Y' ( displaying of any one record is okay) . Justin works in only one department and count is 1 and status should be 'N'. Kimberley does not work anywhere and count is 0 and status should be 'N'.
Expected output:
Employee_ID Department Department_ID Status
Mark Sales D1 Y
Justin Textiles D3 N
Kimberley (null) (null) N
Please help.
I understand that you want to display the first department per user, and add a flag that indicates whether the employee belongs to at least one other department.
You can use window functions:
select
employee_id,
department_name,
department_id
case when cnt <= 1 then 'N' else 'Y' end status
from (
select
emp.employee_id,
dept.department_name,
dept.department_id,
row_number() over(partition by emp.employee_id order by dept.department_id) rn,
count(*) over(partition by emp.employee_id) cnt
from
employee emp
left join department dept on emp.department_id = dept.department_id
) t
where rn = 1
Side note: always use explicit joins (with the on keyword) instead of old-school, implicit joins (with commas in the from clause), whose syntax is harder to read and maintain.
I think this can be easily achieved using group by and keep clause with max as following:
SELECT emp.employee_id,
Max(dept.department_name) keep (dense_rank first order by dept.department_id) as department_name,
Max(dept.department_id) keep (dense_rank first order by dept.department_id) as department_id,
case when count(1) > 1 then 'Y' else 'N' end as status
FROM employee emp
LEFT JOIN department dept ON emp.department_id = dept.department_id
GROUP BY emp.employee_id;
Cheers!!
I am trying to get the max salary of each dept and display that teacher by first name as a separate column. So dept 1 may have 4 rows but one name showing for max salary. I'm Using SQL SERVER
With TeacherList AS(
Select Teachers.FirstName,Teachers.LastName,
Teachers.FacultyID,TeacherID, 1 AS LVL,PrincipalTeacherID AS ManagerID
FROM dbo.Teachers
WHERE PrincipalTeacherID IS NULL
UNION ALL
Select Teachers.FirstName,Teachers.LastName,
Teachers.FacultyID,Teachers.TeacherID, TeacherList.LVL +
1,Teachers.PrincipalTeacherID
FROM dbo.Teachers
INNER JOIN TeacherList ON Teachers.PrincipalTeacherID =
TeacherList.TeacherID
WHERE Teachers.PrincipalTeacherID IS NOT NULL)
SELECT * FROM TeacherList;
SAMPLE OUTPUT :
Teacher First Name | Teacher Last Name | Faculty| Highest Paid In Faculty
Eric Smith 1 Eric
Alex John 1 Eric
Jessica Sewel 1 Eric
Aaron Gaye 2 Aaron
Bob Turf 2 Aaron
I'm not sure from your description but this will return all teachers and the last row is the name of the teacher with the highest pay on the faculty.
select tr.FirstName,
tr.LastName,
tr.FacultyID,
th.FirstName
from Teachers tr
join (
select FacultyID, max(pay) highest_pay
from Teachers
group by FacultyID
) t on tr.FacultyID = t.FacultyID
join Teachers th on th.FacultyID = t.FacultyID and
th.pay = t.highest_pay
this will produce an unexpected result (duplicate rows) if there are more persons with the highest salary on the faculty. In such case you may use window functions as follows:
select tr.FirstName,
tr.LastName,
tr.FacultyID,
t.FirstName
from Teachers tr
join
(
select t.FirstName,
t.FacultyID
from
(
select t.*,
row_number() over (partition by FacultyID order by pay desc) rn
from Teachers t
) t
where t.rn = 1
) t on tr.FacultyID = t.FacultyID
This will display just one random teacher from faculty with highest salary.
dbfiddle demo
You can do this with a CROSS APPLY.
SELECT FirstName, LastName, FacultyID, HighestPaid
FROM Teachers t
CROSS APPLY (SELECT TOP 1 FirstName AS HighestPaid
FROM Teachers
WHERE FacultyID = t.FacultyID
ORDER BY Salary DESC) ca
Tables:
Department (dept_id,dept_name)
Students(student_id,student_name,dept_id)
I am using Oracle. I have to print the name of that department that has the minimum no. of students. Since I am new to SQL, I am stuck on this problem. So far, I have done this:
select d.department_id,d.department_name,
from Department d
join Student s on s.department_id=d.department_id
where rownum between 1 and 3
group by d.department_id,d.department_name
order by count(s.student_id) asc;
The output is incorrect. It is coming as IT,SE,CSE whereas the output should be IT,CSE,SE! Is my query right? Or is there something missing in my query?
What am I doing wrong?
One of the possibilities:
select dept_id, dept_name
from (
select dept_id, dept_name,
rank() over (order by cnt nulls first) rn
from department
left join (select dept_id, count(1) cnt
from students
group by dept_id) using (dept_id) )
where rn = 1
Group data from table students at first, join table department, rank numbers, take first row(s).
left join are used is used to guarantee that we will check departments without students.
rank() is used in case that there are two or more departments with minimal number of students.
To find the department(s) with the minimum number of students, you'll have to count per department ID and then take the ID(s) with the minimum count.
As of Oracle 12c this is simply:
select department_id
from student
group by department_id
order by count(*)
fetch first row with ties
You then select the departments with an ID in the found set.
select * from department where id in (<above query>);
In older versions you could use RANK instead to rank the departments by count:
select department_id, rank() over (order by count(*)) as rnk
from student
group by department_id
The rows with rnk = 1 would be the department IDs with the lowest count. So you could select the departments with:
select * from department where (id, 1) in (<above query>);
I have problems finding a solution to an SQL query. This is probably a very obvious beginner question but I can't seem to get the results that I'm after. I have a table that looks something like the following:
|Name |Station|Salary|
|Bob |1 |2000 |
|Steve|2 |1750 |
|Mark |3 |2050 |
|Lisa |4 |2200 |
|Hans |5 |2000 |
I would like to select the names of the people in this table that have the same salary. The result should of course be Bob and Hans.
If you join the table against itself on Salary but where the names are separate then this should give you any matching salaried people:
SELECT s1.Name, s1.Station, s1.Salary
FROM Staff s1
INNER JOIN Staff s2 ON s1.Salary = s2.Salary AND s1.Name <> s2.Name
Here's a SQLFiddle to show it in action
SELECT Name
FROM table1
WHERE Salary IN (
SELECT Salary
FROM table1
GROUP BY Salary
HAVING COUNT(*) > 1
)
If you determine the salary bands which have more than one employee, you can then join back to it as a derived table:
SELECT e.Name, e.Station
FROM Employee e
INNER JOIN
(
SELECT Salary
FROM Employee
GROUP BY Salary
HAVING COUNT(*) > 1
) grp ON e.Salary = grp.Salary;
SqlFiddle here
Most databases support window functions. The simple method to do this is to count the number of people that have a given salary. Then choose those people. Here is an easy method:
select t.*
from (select t.*, count(*) over (partition by salary) as salarycnt
from table t
) t
where salarycnt > 1
order by salary;
TRY THIS:
SELECT E1.Name, E1.Salary
FROM Employee E1, Employee E2
WHERE E1.Salary = E2.Salary
AND E1.Name <> E2.Name
http://sqlfiddle.com/#!2/1e34b
Use below Query:
with datatab as
(
select 'Bob' Name, 1 Station, 2000 Salary from dual union
select 'Steve' Name, 2 Station, 1750 Salary from dual union
select 'Mark' Name, 3 Station, 2050 Salary from dual union
select 'Lisa' Name, 4 Station, 2200 Salary from dual union
select 'Hans' Name, 5 Station, 2000 Salary from dual union
select 'Test' Name, 6 Station, 1750 Salary from dual
)
SELECT NAME, sTATION, SALARY FROM DATATAB
WHERE SALARY IN
(
SELECT Salary
FROM datatab
GROUP BY Salary
HAVING COUNT(1) > 1
);
As someone suggested in Edits, The Query would be:
SELECT NAME, sTATION, SALARY FROM TABLE_NAME
WHERE SALARY IN
(
SELECT Salary
FROM TABLE_NAME
GROUP BY Salary
HAVING COUNT(1) > 1
)
Select a.name, a.salary from
(
Select count(salary) as cnt, salary from staff group by salary having count(salary) > 1
)as X
Inner join staff a on a.Salary=x.salary
order by a.salary:
Use aliases when you have to put one and the same table two or more times:
select t1.Name,
t2.Name,
t1.Salary
from MyTable t1,
MyTable t2
where t1.Station > t2.Station and -- if Station is id
-- t1.Name > t2.Name -- if Name is in fact an id
t1.Salary = t2.Salary
Try this:
select COUNT(*) as NumberOfPerson,salary from tblEmployee group by salary having COUNT(*)>1
For MySQL:
Select * from worker
where salary in (select salary from worker
group by salary
having count(1)>1);
lets say table name is: employee
select distinct e.name, e.salary from employee e, employee e1 where
e.salary = e1.salary and e.name != e1.name;
First Solution :
Select e1.name from employee e1
inner join employee e2 on e1.salary=e2.salary AND e1.name <> e2.name
Second easy solution:
Select name from employee
where salary In (Select salary from employee
group by salary
having count(*)>1)
SUPPOSE WE HAVE TABLE NAMELY AS EMP3 WHICH ONTEIN COLUMNS AS FIRST_NAME,LAST_NAME,SALRY,DEPARTMENT_ID,COMMISSION ETC.
NOW WE HAVE TO SELECT RECORDS OF EMPLOYEES WHO HAVE THE SAME SALARY.
LET'S GET OUTPUT WITH THE HELP OF SELF JOIN.
HERE WE ARE JOINING THE SAME TABLE WITH ITSELFMTO GET RECORDS WHO HAVE THE SAME SALARY.
SELECT E1.FIRST_NAME AS FN,E1.SALARY FROM EMPLOYEES E1 INNER JOIN EMPLOYEES E2 ON E1.SALARY=E2.SALARY;
Treating same table as a separate two table.
SELECT DISTINCT T.username, T.salary
FROM account T, account T
WHERE T.salary = T.salary
AND T.username <> T.username
ORDER BY salary;
Do you want the quantity of people with the same salary.
SELECT count(*) FROM table GROUP BY salary