SQL query to find active employees - sql

Sql query to find the active employees. sort the output in descending order based on employee id column and fetch only the first 15 records.
Display employee id, employee name, city, state, country,salary, active date, status, department name, manager name.
employee name: concatenate firstname & lastname with space character and fetch only first 10 letters from employee name
manager name: display firstname and lastname(separated by space)
Tables:
EMPLOYEE--dept_id,emp_activefrom, emp_dob, emp_fname, emp_lname, emp_sal, emp_status, emp_terminationdate, loc_id, mgr_id
LOCATION-- city, country, loc_id, state
DEPARTMENT--dept_head,dept_id, dept_name
the below given is the code which i used,
SELECT b.* FROM (SELECT e.emp_id, SUBSTR(e.emp_fname||' '||e.emp_lname,1,10) AS emp_name, l.city, l.state, l.country, e.emp_sal, e.emp_activefrom, e.emp_status,d.dept_name, d.dept_head FROM employee e, location l, department d WHERe e.dept_id=d.dept_id AND e.loc_id=l.loc_id AND e.emp_status='Active' ORDER BY 1 desc) b WHERE rownum<=15;
I dont know what is wrong here. please help me out to solve this.

It's always better use proper join for better understanding. To get the manager name self join (employee e inner jion employee m) is used here.
SELECT e.emp_id, SUBSTR(e.emp_fname||' '||e.emp_lname,1,10) AS emp_name, l.city, l.state, l.country, e.emp_sal, e.emp_activefrom,
e.emp_status,d.dept_name, d.dept_head , m.emp_fname||' '||m.emp_lname as manager_name
FROM employee e
inner join department d on e.dept_id=d.dept_id
inner join location l on e.loc_id=l.loc_id
inner join employee m on e.Mgrid=m.EmpId
where e.emp_status='Active' and
rownum<=15
order by e.EmpId desc

Kazi is correct that you want to do this using JOINs. However you need to be careful about employees that have no managers when doing the JOIN. In addition, Oracle is finicky about limiting the number of rows -- and I assume you are using Oracle based on rownum comparisons. The correct method uses the fetch first clause.
So, you seem to be describing something like this:
select e.emp_id, substr(e.emp_fname || ' ' || e.emp_lname,1,10) AS emp_name,
l.city, l.state, l.country,
e.emp_sal, e.emp_activefrom, e.emp_status,
d.dept_name, d.dept_head,
(m.emp_fname || ' ' || m.emp_lname) as manager_name
from employee e join
department d
on e.dept_id = d.dept_id join
location l
on e.loc_id = l.loc_id left join
employee m
on e.Mgrid = m.EmpId
where e.emp_status = 'Active'
order by e.EmpId desc
fetch first 15 rows only;

Related

Join two table with department wise maximum salary

Department wise maximum salary in a table it's working:
select * from employee where (emp_dept, emp_sal)
in (select emp_dept, max(emp_sal) from employee group by emp_dept);
but my concern is : i want emp_id, emp_name, emp_sal, emp_dept column with department wise maximnum salary
customer table : cust_id, cust_name, emp_id
employee table : emp_id, emp_name, emp_sal, emp_dep
I think you want :
select e.emp_id, e.emp_name, e.emp_sal, e.emp_dept
from employee e
where e.emp_sal = (select max(e1.emp_sal) from employee e1 where e1.emp_dept = e.emp_dept);
Assuming you want all the records from the employee table with the maximum salary added, then you could use something like:
Select e.emp_id, e.emp_name, e.emp_sal, e.emp_dept, d.max_salary
from employee e
left join
(select emp_dept,max(emp_sal) as max_salary
from employee
group by emp_dept) d
ON e.emp_dept=d.emp_dept
The sub query calculates the maximum salary for each department and then using the left join you can get it into the final table.
If you want the employee details of the employee with the maximum salary, then:
Select e.emp_id, e.emp_name, e.emp_sal, e.emp_dept, d.max_salary
from employee e
inner join
(select emp_dept,max(emp_sal) as max_salary
from employee
group by emp_dept) d
ON e.emp_dept=d.emp_dept and e.emp_sal=d.max_salary
In this case the join is based on the salary component as well, thereby returning only the employees with the maximum salary. Hope this helps.
Just use a window function:
select e.*,
max(emp_sal) over (partition by emp_dept) as dept_max_sal
from employee ;

Write a query to display the name of the department that has the maximum student count

this is the schema Write a query to display the name of the department that has the maximum student count.
this is what is tried.
select d.department_name,count(s.student_id)
from department d left join student s
on d.department_id=s.department_id
group by d.department_name,d.department_id
order by d.department_name;
and i think there is something missing in my code
You're almost there.
Order the result in descending order on the number of students and then take the first row:
SELECT department_name
FROM
(
SELECT d.department_name,
COUNT(*) AS nr_students
FROM department d
JOIN student s
ON d.department_id = s.department_id
GROUP BY d.department_name
ORDER BY nr_students DESC
)
WHERE ROWNUM <= 1;
Based on the schema mentioned, you would have to make a join (INNER JOIN) to the department table from the staff table to get the name of the department.
If the name of the department is not desired and the counts can just be based on the department_id, then a join is not required.
The queries for both the scenarios is mentioned below.
Oracle SQL query for result with the department name, i.e. with INNER JOIN
SELECT D.DEPARTMENT_NAME, COUNT(S.DEPARTMENT_ID) AS STAFF_COUNT FROM **DEPARTMENT D, STAFF S** --INDICATES INNER JOIN IN ORACLE SQL
WHERE D.DEPARTMENT_ID = S.DEPARTMENT_ID
GROUP BY D.DEPARTMENT_NAME
ORDER BY STAFF_COUNT DESC
Oracle SQL query for result without the department name, just the department_id
SELECT S.DEPARTMENT_ID,COUNT(S.DEPARTMENT_ID) AS STAFF_COUNT FROM STAFF S
GROUP BY S.DEPARTMENT_ID
ORDER BY STAFF_COUNT DESC
Hope this helps. Cheers.
I tried this and it worked.
select department_name
from department d inner join student s
on s.department_id=d.department_id
having count(*) in (
select max(count(student_id))
from student s join department d
on d.department_id=s.department_id
group by d.department_id)
group by d.department_id,department_name;
Select * from (
SELECT D.DEPARTMENT_NAME, COUNT(S.DEPARTMENT_ID) AS STAFF_COUNT
FROM DEPARTMENT D, STAFF S
WHERE D.DEPARTMENT_ID = S.DEPARTMENT_ID
GROUP BY D.DEPARTMENT_NAME
ORDER BY STAFF_COUNT DESC)
where rownum=1;
This query will give department name that has maximum number of student count

TROUBLE IN MULTIPLE SUBSELECT QUERY

I need to find the name, function, officename and the salary of all employee with the same function as PETER or a salary greater or equal than the salary of SANDERS. order by function and salary.
There are two tables: office and employee
table office contains:
officenumber
name
city
table employee contains:
employeenumber
name
function
manager
sal
officenumber
this is my current SQL query:
SELECT NAME,
FUNCTION,
SAL
FROM EMPLOYEE
WHERE FUNCTIE = (SELECT FUNCTION
FROM EMPLOYEE
WHERE NAME = 'PIETERS')
I'm stuck with the query.
Assuming this is SQL Server (you never specified), something like this should work.
SELECT
e.name,
e.function,
e.sal,
o.name AS officename
FROM employee e
JOIN office o ON e.officenumber = o.officenumber
WHERE
e.function = (SELECT function FROM employee WHERE name = 'PIETERS') OR
e.sal >= (SELECT sal FROM employee WHERE name = 'SANDERS')
ORDER BY e.function, e.salary
You'll have to tweak this a bit if you're working with MySQL or something else.
Three things you need to do here:
1. join the two tables, since you need results from both tables
2. filter the results according to the two criterias
3. order the results:
The first part is easy, just need to join them according to the officenumber:
select e.name, e.function, o.name as officeName, e.salary from
employee e inner join office o
on e.officenumber = o.officenumber
second part, simple where clause:
where e.function = (select function from employee where name = 'PETER')
or e.salary >= (select salary from employee where name = 'SANDERS')
and the last, ordering:
order by e.function, e.salary
Putting it all together:
select e.name, e.function, o.name as officeName, e.salary from
employee e inner join office o
on e.officenumber = o.officenumber
where e.function = (select function from employee where name = 'PETER')
or e.salary >= (select salary from employee where name = 'SANDERS')
order by e.function, e.salary

Include rows that contain null values in a particular column with inner join

The goal here is to return the ID, Name, and Manager Name and ID for each Employee. The table does not contain a manager name, only a manager ID for a given employee. The current query works great using an inner join, except that one employee does not have a manager ID (he's the boss), and so none of his information appears. The current query looks like this:
SELECT DISTINCT e.employee_id AS EMPLOYEE_ID,
e.FULL_NAME AS EMPLOYEE_NAME,
m.manager_ID AS REPORTS_TO,
m.FULL_NAME AS MANAGER_NAME
FROM EMPS e
INNER JOIN EMPS m ON e.manager_id = m.employee_id;
How can I include the name and information for this employee despite his lack of a seemingly necessary field? Thanks
If you want to include the employee name when there is no manager do a left join:
SELECT DISTINCT e.employee_id AS EMPLOYEE_ID,
e.FULL_NAME AS EMPLOYEE_NAME,
m.manager_ID AS REPORTS_TO,
m.FULL_NAME AS MANAGER_NAME
FROM EMPS e
LEFT JOIN EMPS m ON e.manager_id = m.employee_id;

Employees with largest salary in department

I found a couple of SQL tasks on Hacker News today, however I am stuck on solving the second task in Postgres, which I'll describe here:
You have the following, simple table structure:
List the employees who have the biggest salary in their respective departments.
I set up an SQL Fiddle here for you to play with. It should return Terry Robinson, Laura White. Along with their names it should have their salary and department name.
Furthermore, I'd be curious to know of a query which would return Terry Robinsons (maximum salary from the Sales department) and Laura White (maximum salary in the Marketing department) and an empty row for the IT department, with null as the employee; explicitly stating that there are no employees (thus nobody with the highest salary) in that department.
Return one employee with the highest salary per dept.
Use DISTINCT ON for a much simpler and faster query that does all you are asking for:
SELECT DISTINCT ON (d.id)
d.id AS department_id, d.name AS department
,e.id AS employee_id, e.name AS employee, e.salary
FROM departments d
LEFT JOIN employees e ON e.department_id = d.id
ORDER BY d.id, e.salary DESC;
->SQLfiddle (for Postgres).
Also note the LEFT [OUTER] JOIN that keeps departments with no employees in the result.
This picks only one employee per department. If there are multiple sharing the highest salary, you can add more ORDER BY items to pick one in particular. Else, an arbitrary one is picked from peers.
If there are no employees, the department is still listed, with NULL values for employee columns.
You can simply add any columns you need in the SELECT list.
Find a detailed explanation, links and a benchmark for the technique in this related answer:
Select first row in each GROUP BY group?
Aside: It is an anti-pattern to use non-descriptive column names like name or id. Should be employee_id, employee etc.
Return all employees with the highest salary per dept.
Use the window function rank() (like #Scotch already posted, just simpler and faster):
SELECT d.name AS department, e.employee, e.salary
FROM departments d
LEFT JOIN (
SELECT name AS employee, salary, department_id
,rank() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rnk
FROM employees e
) e ON e.department_id = d.department_id AND e.rnk = 1;
Same result as with the above query with your example (which has no ties), just a bit slower.
This is with reference to your fiddle:
SELECT * -- or whatever is your columns list.
FROM employees e JOIN departments d ON e.Department_ID = d.id
WHERE (e.Department_ID, e.Salary) IN (SELECT Department_ID, MAX(Salary)
FROM employees
GROUP BY Department_ID)
EDIT :
As mentioned in a comment below, if you want to see the IT department also, with all NULL for the employee records, you can use the RIGHT JOIN and put the filter condition in the joining clause itself as follows:
SELECT e.name, e.salary, d.name -- or whatever is your columns list.
FROM employees e RIGHT JOIN departments d ON e.Department_ID = d.id
AND (e.Department_ID, e.Salary) IN (SELECT Department_ID, MAX(Salary)
FROM employees
GROUP BY Department_ID)
This is basically what you want. Rank() Over
SELECT ename ,
departments.name
FROM ( SELECT ename ,
dname
FROM ( SELECT employees.name as ename ,
departments.name as dname ,
rank() over (
PARTITION BY employees.department_id
ORDER BY employees.salary DESC
)
FROM Employees
JOIN Departments on employees.department_id = departments.id
) t
WHERE rank = 1
) s
RIGHT JOIN departments on s.dname = departments.name
Good old classic sql:
select e1.name, e1.salary, e1.department_id
from employees e1
where e1.salary=
(select maxsalary=max(e.salary) --, e. department_id
from employees e
where e.department_id = e1.department_id
group by e.department_id
)
Table1 is emp - empno, ename, sal, deptno
Table2 is dept - deptno, dname.
Query could be (includes ties & runs on 11.2g):
select e1.empno, e1.ename, e1.sal, e1.deptno as department
from emp e1
where e1.sal in
(SELECT max(sal) from emp e, dept d where e.deptno = d.deptno group by d.dname)
order by e1.deptno asc;
SELECT
e.first_name, d.department_name, e.salary
FROM
employees e
JOIN
departments d
ON
(e.department_id = d.department_id)
WHERE
e.first_name
IN
(SELECT TOP 2
first_name
FROM
employees
WHERE
department_id = d.department_id);
`select d.Name, e.Name, e.Salary from Employees e, Departments d,
(select DepartmentId as DeptId, max(Salary) as Salary
from Employees e
group by DepartmentId) m
where m.Salary = e.Salary
and m.DeptId = e.DepartmentId
and e.DepartmentId = d.DepartmentId`
The max salary of each department is computed in inner query using GROUP BY. And then select employees who satisfy those constraints.
Assuming Postgres
Return highest salary with employee details, assuming table name emp having employees department with dept_id
select e1.* from emp e1 inner join (select max(sal) avg_sal,dept_id from emp group by dept_id) as e2 on e1.dept_id=e2.dept_id and e1.sal=e2.avg_sal
Returns one or more people for each department with the highest salary:
SELECT result.Name Department, Employee2.Name Employee, result.salary Salary
FROM ( SELECT dept.name, dept.department_id, max(Employee1.salary) salary
FROM Departments dept
JOIN Employees Employee1 ON Employee1.department_id = dept.department_id
GROUP BY dept.name, dept.department_id ) result
JOIN Employees Employee2 ON Employee2.department_id = result.department_id
WHERE Employee2.salary = result.salary
SQL query:
select d.name,e.name,e.salary
from employees e, depts d
where e.dept_id = d.id
and (d.id,e.salary) in
(select dept_id,max(salary) from employees group by dept_id);
Take look at this solution
SELECT
MAX(E.SALARY),
E.NAME,
D.NAME as Department
FROM employees E
INNER JOIN DEPARTMENTS D ON D.ID = E.DEPARTMENT_ID
GROUP BY D.NAME