I'm messing around in my school's database and I am trying to count the null values in this query:
SELECT Depart_ID, DepartName,
COUNT(Name) AS employees,
SUM(Salary) AS 'Total salary'
FROM Ch4Employee AS E
INNER JOIN Ch4Department AS D
ON E.Depart_ID = D.ID
GROUP BY Depart_ID, DepartName
Any tips?
If you want to count NULL salaries, do count(*) - count(salary), because count(*) counts all rows, and count(salary) counts the non-null values.
E.g.
SELECT Depart_ID, DepartName,
COUNT(Name) AS employees,
SUM(Salary) AS 'Total salary',
COUNT(*) - COUNT(Salary) AS null_salaries
FROM Ch4Employee AS E
INNER JOIN Ch4Department AS D
ON E.Depart_ID = D.ID
GROUP BY Depart_ID, DepartName
select Depart_ID, DepartName, COUNT(Name) as employees, SUM(Salary) as 'Total salary' from Ch4Employee AS E
inner join Ch4Department as D on E.Depart_ID = D.ID
group by Depart_ID, DepartName
HAVING COUNT(Name) = 0
If you want to check the values after aggregation you have to use Having.
Related
I need to find the maximum average salary per department. Then I need to return only departments (NAME and DEPT_MAX_AVG_SALARY) that have that maximum average salary with two decimal places (i.e., it might be more than one that have the same max average salary, and that is fine, we need all departments that equal that amount).
SELECT p.DEPARTMENT_ID, d.NAME, cast(AVG(p.SALARY) as decimal(18,2)) as AVERAGE
FROM PROFESSOR p
INNER JOIN DEPARTMENT d ON p.DEPARTMENT_ID = d.ID
GROUP BY p.DEPARTMENT_ID, d.NAME
HAVING AVG(p.SALARY) =
(
SELECT TOP 1 AVG(a.SALARY) as MAXAVERAGE
FROM PROFESSOR a
INNER JOIN DEPARTMENT b
ON a.DEPARTMENT_ID = b.ID
GROUP BY a.DEPARTMENT_ID
ORDER BY MAXAVERAGE DESC
)
ORDER BY AVERAGE DESC
Is there a better way to do this?
select max(d.avg) from (
select avg(salary) "avg" from professor group by department
) as d
This is obviously a stripped down version but the logic is there. You select the max from the average computed in the derived table, which is grouped by the department.
I suggest that you should try WITH TIES and ORDER BY:
Select TOP 1 WITH TIES
d.NAME as dep_name
,AVG(cast(p.SALARY as decimal(18,2)) as avg_dep_salary
From PROFESSOR p
Inner join DEPARTMENT d on p.DEPARTMENT_ID = d.ID
Group by
d.ID
,d.NAME
Order by avg_dep_salary desc
TOP (1) WITH TIES is the way to go. But I think the query looks like this:
select top (1) with ties d.id, d.NAME as dep_name,
cast(avg(p.SALARY) as decimal(18, 2)) as avg_dep_salary
from PROFESSOR p Inner join
DEPARTMENT d
on p.DEPARTMENT_ID = d.ID
group by d.ID, d.NAME
order by avg_dep_salary desc;
It is important to cast the value after calculating the average. If salary is an integer, then you may need:
cast(avg(p.SALARY * 1.0) as decimal(18, 2)) as avg_dep_salary
I have data of two tables. In the first table I have employee id's and their names. In the second table, I have employee details (such as salary, location, join date, projects handled, designation).
I am trying to write a query where I can bring the data of maximum and minimum salary group by location and designation. This is what I have so far:
SELECT E.EMPID,I.EMPID, E.EMPNAME, I.EMPNAME,
B.[MAXIMUM SALARY],F.[MINIMUM SALARY],
B.DESIG,F.DESIG,B.LOCATION,F.LOCATION
FROM
((SELECT MAX (SALARY) [MAXIMUM SALARY], LOCATION, DESIG
FROM
EMPDETAILS
GROUP BY LOCATION, DESIG) B
JOIN
(SELECT C.EMPID,C.SALARY,C.GENDER,C.DESIG,
C.JOINON,C.LOCATION,C.PROJECTS,D.EMPNAME
FROM EMPDETAILS C
JOIN
EMPLOYEE D
ON C.EMPID=D.EMPID) E
ON E.DESIG=B.DESIG AND E.SALARY=B.[MAXIMUM SALARY] AND E.LOCATION =
B.LOCATION)
FULL OUTER JOIN[enter image description here][1]
((SELECT MIN(SALARY) AS [MINIMUM SALARY], LOCATION, DESIG
FROM EMPDETAILS
GROUP BY LOCATION, DESIG) F
JOIN
(SELECT G.EMPID,H.EMPNAME,G.DESIG,G.GENDER,
G.JOINON,G.LOCATION,G.PROJECTS,G.SALARY
FROM EMPDETAILS G
JOIN EMPLOYEE H
ON G.EMPID=H.EMPID) I
ON I.DESIG=F.DESIG AND F.[MINIMUM SALARY]=I.SALARY AND
I.LOCATION=F.LOCATION)
ON I.DESIG=E.DESIG
ORDER BY B.LOCATION, f.location
Giving me:
no clue what you really want/need, but if you want employeeID-level results, you'll need something like:
SELECT
d.*,
min_salary,
max_salary
FROM
EMPDETAILS d JOIN
EMPLOYEE e ON
d.EMPID=e.EMPID JOIN
(SELECT
empid,
MIN(salary) AS min_salary,
MAX(salary) AS max_salary
FROM
EMPDETAILS
GROUP BY
empid) m ON
e.empid = m.empid
if you want min/max salaries grouped by LOCATION, DESIG as in your code, you'll need to return those results separately from employee-level details:
SELECT
LOCATION, DESIG,
MIN(salary) AS min_salary,
MAX(salary) AS max_salary
FROM
EMPDETAILS
GROUP BY
LOCATION, DESIG
you don't need separate subqueries for your min and max groupings, you don't need to join your detail tables multiple times, and you don't need a full outer join.
My tables are structured like this (there are more values in the tables but I only wrote the ones relevant to this):
Department(dep_id, dep_name)
Employee(dep_id)
I need to display dep_name and the number of employees in every department, except once specific department (let's call it DepX) and only the departments with more than one employee.
I tried multiple methods to solve this but none of them worked.
Some methods I tried:
SELECT department.dep_name, COUNT(employee.dep_id) AS NumberOfEmployees FROM employee
INNER JOIN department ON employee.dep_id=department.dep_id
WHERE dep_name<>'DepX'
GROUP BY dep_id
HAVING COUNT(employee.dep_id) > 1;
SELECT dep_name FROM department
WHERE dep_name <>'DepX'
UNION
SELECT COUNT(*) FROM employee
WHERE COUNT(*) > 1
GROUP BY dep_id;
I can't figure this out. Thanks!
The first example does now work because you're including dep_name in your results without an aggregation but not grouping on it.
You can either use the department name in your grouping instead of the ID:
SELECT department.dep_name, COUNT(employee.dep_id) AS NumberOfEmployees FROM employee
INNER JOIN department ON employee.dep_id=department.dep_id
WHERE dep_name<>'DepX'
GROUP BY department.dep_name
HAVING COUNT(employee.dep_id) > 1;
or do the COUNT in a subquery:
SELECT department.dep_name,
e.NumberOfEmployees
FROM department
INNER JOIN (SELECT dep_id,
COUNT(*) NumberOfEmployees
FROM employee
GROUP BY dept_id
HAVING COUNT(dept_id) > 1
) e
ON department.dep_id = e.dep_id
WHERE dep_name<>'DepX'
SELECT department.dep_name, COUNT(employee.dep_id) AS NumberOfEmployees FROM employee
INNER JOIN department ON employee.dep_id=department.dep_id
WHERE department.dep_name not in('DepX')
GROUP BY department.dep_name
HAVING COUNT(employee.dep_id) > 1;
update your table alias per your need
TEST this. This query help you return not only dept_name, it can return all fields from Department if you want:
SELECT d.*, A.numOfEmployees
FROM Department d,
(
SELECT e.dep_id, COUNT(*) numOfEmployees
FROM Employee e
GROUP BY e.dep_id
HAVING COUNT(*) > 1
) A
WHERE d.dep_id = A.dep_id
AND d.dep_name != 'DepX'
Calculate the minimum salary for exempt employees and the average salary for non-exempt employees in a SINGLE SQL statement. Use subqueries to incorporate both elements in the query. It should look something like:
Min Exempt Salary Average Non-Exempt Salary
47,000 35,271
I know how to do it separate but cannot figure how to do it as it stated above , this is the statments I have.
SELECT jobs1.exempt_nonexempt_status,
Min (employees.salary)AS Minimal_Exempt_Salary
FROM employees
LEFT JOIN jobs1
ON employees.job_title = jobs1.job_title
WHERE jobs1.exempt_nonexempt_status = 'Exempt'
GROUP BY jobs1.exempt_nonexempt_status
SELECT jobs1.exempt_nonexempt_status,
Avg (employees.salary)AS Average_Non_Exempt_Salary
FROM employees
LEFT JOIN jobs1
ON employees.job_title = jobs1.job_title
WHERE jobs1.exempt_nonexempt_status = 'Non-exempt'
GROUP BY jobs1.exempt_nonexempt_status
Try this:
SELECT
MIN(CASE WHEN J.exempt_nonexempt_status = 'Exempt'
THEN E.Salary
END) AS Minimal_Exempt_Salary,
SUM(CASE WHEN J.exempt_nonexempt_status = 'Non-exempt'
THEN E.Salary
END) AS Average_Non_Exempt_Salary
FROM Employees E
LEFT JOIN JOBS1 J ON J.job_title = E.job_title
WHERE J.exempt_nonexempt_status IN ('Exempt', 'Non-exempt')
A normal way to do this would be:
select j.exempt_nonexempt_status
, avg(case when j.exempt_nonexempt_status='Non-exempt' then e.salary end)
as Average_Non_Exempt_Salary
, min(case when j.exempt_nonexempt_status='Exempt' then e.salary end)
as Minimal_Exempt_Salary
from Employees e
left join
jobs1 j
on e.job_title = j.job_title
group by
j.exempt_nonexempt_status
But that doesn't use subqueries. Another way is to wrap your two queries in an outer select:
select (
select MIN (employees.salary)
from Employees left join jobs1
on employees.job_title = jobs1.job_title
where jobs1.exempt_nonexempt_status='Exempt'
group by jobs1.exempt_nonexempt_status
) as MinimalExemptSalary
, (
select avg (employees.salary)
from Employees left join jobs1
on employees.job_title = jobs1.job_title
where jobs1.exempt_nonexempt_status='Non-exempt'
group by jobs1.exempt_nonexempt_status
) as AverageNonExemptSalary
I have 2 tables in the following format:
employee (employeeID, EmployeeName, DepartmentID)
departments (DepartmentID, DeptName)
How many employees there are who work in each of the departments that have more employees than the average number of employees in a department.
im looking to the results in the following format:
Dept Name | Num of Emp
engineering | 10
science | 15
SELECT deptName, cnt
FROM (
SELECT departmentID, COUNT(*) AS cnt
FROM employee
GROUP BY
departmentID
HAVING COUNT(*) >=
(
SELECT AVG(cnt)
FROM (
SELECT COUNT(*) AS cnt
FROM employee
GROUP BY
departmentID
)
)
) e
JOIN departments d
ON d.departmentID = e.departmentID
In Oracle, you can use analytic functions which are more elegant:
SELECT DeptName, cnt
FROM (
SELECT q.*, AVG(cnt) OVER() AS acnt
FROM (
SELECT departmentID, COUNT(*) AS cnt
FROM employee
GROUP BY
departmentID
) q
) e
JOIN departments d
ON d.departmentID = e.departmentID
WHERE cnt >= acnt
since an employee can be in only one department, the average number of employees is just the total # of employees over the total number of departments. So how about:
SELECT dept.name, COUNT(emp.id) AS employeeCount
FROM emp INNER JOIN dept ON emp.deptId = dept.id
GROUP BY dept.name
HAVING (COUNT(emp.id) >
(SELECT COUNT(*) FROM emp) /
(SELECT COUNT(*) FROM dept))