Find out employees average Salary greater than 8000 within their Department - oracle

I am trying to find the employees average salary greater than 8000 within their department
I got the avg(salary) within the department greater than 8000 but could not display the names
select avg(salary) from employees group by department_id having avg(salary)> 8000
it show the employees name

Try this:
Select department_id, emp_name, salary from
(select department_id, emp_name, salary, avg(salary) over(partition by department_id) as avg_salary
from employees)
Where avg_salary >= 8000
AND salary >= 8000; -- ADDED THIS CONDITION
Above query will return all the employees within the department having average salaries of employees greater than 8000 with department id, employee name and their salary.
Cheers!!

Related

Finding list of max average salary, department wise, whilst displaying both max average salary and department_id

When I try it without displaying department_id it works fine as :
SQL> SELECT MAX(AVG(SALARY)) FROM EMPLOYEE GROUP BY DEPARTMENT_ID;
MAX(AVG(SALARY))
----------------
800000
But when I want to display the department_id's too, it gives me error as follows:
SQL> SELECT DEPARTMENT_ID, MAX(AVG(SALARY)) FROM EMPLOYEE GROUP BY DEPARTMENT_ID;
SELECT DEPARTMENT_ID, MAX(AVG(SALARY)) FROM EMPLOYEE GROUP BY DEPARTMENT_ID
*
ERROR at line 1:
ORA-00937: not a single-group group function
Is there any explanation for this? What am I doing wrong? I went through answers of previous questions like this and tried their solutions but got same or some other error. Any help would be appreciated.
I suggest you use
SELECT department_id, avg_salary
FROM ( SELECT DEPARTMENT_ID,
AVG (SALARY) avg_salary,
RANK () OVER (ORDER BY AVG (salary) DESC) rnk
FROM EMPLOYEE
GROUP BY DEPARTMENT_ID)
WHERE rnk = 1;
i.e.
use your first query as a "source"
additionally, rank average salaries in descending order (using the rank analytic function)
select row which ranks as highest

Employees with the lower salary than the average in their dept

I got two challenges on my college exam to do.
The first one is to Show data for employees (name, salary, and department) who are paid less than the average salary for their department.
I tried this:
SELECT ename, sal, deptno
FROM Emp
WHERE sal < (SELECT AVG(sal) FROM EMP)
GROUP BY deptno;
But i get the ORA-00979: not a GROUP BY expression error.
The other one i didn't started but is quite the same, Show the data of employees (name, commission and department) who receive commission greater than the average commission in their department.
ps: I'm starting with SQL so the topic isn't very deep yet.
You can use a window function for this
SELECT ename, sal, deptno
FROM (
SELECT *,
AVG(sal) OVER (PARTITION BY deptno) AS AvgPerDept
FROM Emp
) AS Emp
WHERE sal < AvgPerDept
Your attempt to the first one is not correct
The expression SELECT AVG(sal) FROM EMP will give the average salary of everyone, regardless which department they're in.
To get the average for each deparment, you will need to GROUP BY dept_no
SELECT Emp.* , dept_salary.average_sal
FROM Emp
INNER JOIN
-- join with an average salary for each department
(
SELECT deptno, AVG(sal) as average_sal
FROM Emp
GROUP BY deptno
) dept_salary
ON Emp.deptno = dept_salary.deptno
WHERE Emp.dept_no = dept_salary.deptno AND Emp.sal < dept_salary.average_sal;

Find second highest salary in each department using rank/dense_rank in hive

These were the two questions asked to me during an interview but only condition is to use rank/dense_rank.
Find second highest salary in each department using rank/dense_rank in
hive.
When there are sufficient records in each department.
When there is only 1 record in few departments.
Guide me if this is even valid or not.
If yes then what should be the queries for the same.
If you need to select all second salary employees then use
dense_rank() over(partition by department order by salary desc) = 2 filter. It will return all employees with second salary.
When there is only 1 record in the department (no second salary exists, one employee in the department), it will be ranked 1 and you will get no records for that department filtering by dense_rank = 2.
If you need to select only one record (not all employees) with second salary then row_number() over(partition by department order by salary desc) = 2 will work, but it will pick one random employee with second salary if there are many employees with second salary. Only one record will be marked with row_number = 2.
Try this:
WITH RESULT AS
(
SELECT salary, DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS SecondHighest FROM Employee
)
SELECT IFNULL(( SELECT salary FROM RESULT WHERE SecondHighest = 2 ORDER BY salary) , NULL) as SecondHighestSalary

Counting the Maximum Number of Values

I have a data table Employees, I want to show all the employees who have been hired on the same day on which the maximum number of employees has been hired. Here's my code:
select last_name, hire_date, count(*) as "Number of Employees Hired"
from employees
group by last_name, hire_date
where hire_date = max(count(*));
However, this code shows "SQL Command Not Properly Ended" error when I run it. How do I fix it so that it runs correctly?
This may not be the cleanest way, but I think will do the trick:
SELECT last_name,
max_hire.hire_date,
max_hire.cnt
FROM
(SELECT *
FROM
(SELECT hire_date,
COUNT(*) cnt
FROM employees
GROUP BY hire_date
ORDER BY COUNT(*) DESC
)
WHERE rownum = 1
) max_hire
INNER JOIN employees
ON employees.hire_date = max_hire.hire_date
Firstly, you should use WHERE before the GROUP BY clause and secondly you should use the aggregate function (count) correctly, as in your case count(*) cannot be compared within the WHERE clause.
You can go with the approach below without using where: (Tested under MySQL)
select last_name, hire_date, count(*) as "Number of Employees Hired"
from employees
group by last_name, hire_date
Order by "Number of Employees Hired" desc limit 1
Hope this helps. Cheers.

How to get only the one employee name from each department if the max salary is same from more than one employee

I am using below query:
SELECT rownum, job_id, employee_id, first_name, last_name, phone_number, salary
FROM employees OUTER
WHERE salary =
(
SELECT MAX(salary)
FROM employees
WHERE job_id = OUTER.job_id
GROUP BY job_id
)
AND ROWNUM < 6;
And getting below result:
1 AD_PRES 100 Steven King 515.123.4567 24000
2 AD_VP 101 Neena Kochhar 515.123.4568 17000
3 AD_VP 102 Lex De Haan 515.123.4569 17000
4 IT_PROG 103 Alexander Hunold 590.423.4567 9000
5 FI_MGR 108 Nancy Greenberg 515.124.4569 12008
But the problem is I want only one name for each JOB_ID. And that should be decided by alphabetical preference in FIRST_NAME.
One option would be to use a subquery which contains the job_id for the first name you want to retain. I wrapped your original query in a common table expression to make it more readable.
WITH t AS
(
SELECT rownum, job_id, employee_id, first_name, last_name,
phone_number, salary
FROM employees OUTER
WHERE salary =
(
SELECT MAX(salary)
FROM employees
WHERE job_id = OUTER.job_id
GROUP BY job_id
)
AND ROWNUM < 6;
)
SELECT t1.rownum, t1.job_id, t1.employee_id, t1.first_name, t1.last_name,
t1.phone_number, t1.salary
FROM t t1
INNER JOIN
(
SELECT job_id, MAX(first_name) AS max_name
FROM t
GROUP BY job_id
) t2
ON t1.job_id = t2.job_id AND t1.first_name = t2.max_name
Use analytic functions:
select * from (
SELECT job_id, employee_id, first_name, last_name, phone_number, salary,
RANK() over (
job_id
order by
salary desc,
first_name,
employee_id -- adding employe_id breaks ties in the ordering
) as rnk
FROM employees
) where rnk = 1;
This will probably also perform better then the subselect.
All this is written without a database at hand, so it might/will contain typos

Resources