--- SQL QUERY --- Which employees are older than their manager? - sql

I have a table named employee. It includes managers and employees. There is also birthdate column and i need to find "older employees than THEIR managers". How can I do it? Could you give me some clue?

You could use an inner join to the same table:
select e.*
from employees e
inner join employees m
on e.managerid = m.id
and e.birthdate < m.birthdate
or exists() in the where:
select e.*
from employees e
where exists (
select 1
from employees m
where e.managerid = m.id
and e.birthdate < m.birthdate
)

If your employees structure is something like:
id,
name,
birthdate,
manager_id
This could be a solution:
select id, name
from employees e
where
exists
(select *
from employees m
where
m.id = e.manager_id and
m.birthdate > e.birthdate);

Related

find all employees' names who has a manager that lives in the same city as them

I am trying to figure out how to "find all employees' name who has a manager that lives in the same city as them." For this problem, we have two tables. We need to make a query.
"employee"
The employee table that we can refer to has both normal employees and managers
employeeid
name
projectid
city
1
jeff
1
new york
2
larry
1
new york
3
Linda
2
detroit
4
tom
2
LA
"Managertable"
Our manager table which we can refer to with mangerid = employeeid
projectid
mangerid
1
2
2
3
Right now I have found a way to get just the employees and filter out the managers, but now I am trying to figure out the next step to get to the comparison of managers and employees. Would this just be another subquery?
SELECT name
FROM employee e
WHERE employeeid not in(
SELECT mangerid
FROM Managertable pm
INNER JOIN employee e
ON pm.mangerid= e.employeeid);
Expected result :
employee name
jeff
I think the easient way to achieve this would be like this:
SELECT
e.*
FROM employee e
inner join Managertable mt on e.projectid = mt.projectid
inner join employee manager on mt.mangerid = manager.employeeid
WHERE
e.city = manager.city
and e.employeeid <> manager.employeeid;
One approach is a correlated subquery in which we look up the employee's manager's city.
select e.name
from employee e
where city =
(
select m.city
from managertable mt
join employee m on m.employeeid = mt.managerid
where mt.projectid = e.projectid
and m.employeeid <> e.employeeid
);
The same thing can be written with an EXISTS clause, if you like that better.
Based off the table structure you're showing, something like this might work
First find the employee ids of employees who have managers in the same city, then join it back on employee to retrieve all data from the table
;WITH same_city AS (
SELECT DISTINCT e.employeeid
FROM employee AS e
INNER JOIN managertable AS mt ON e.projectid = mt.projectid
INNER JOIN employee AS m ON mt.managerid = e.employeeid
WHERE e.city = m.city
)
SELECT e.*
FROM employee
INNER JOIN same_city AS sc ON e.employeeid = sc.employeeid
I don't see how projectid is relevant in your question because you didn't mention that as a requirement or restriction. Here's a method using a CTE to get the managers and their cities, then join to it to find employees who live in the same city as a manager.
with all_managers as (
select distinct m.managerid, e.city
from manager m
join employee e
on m.managerid = e.employeeid
)
select e.name
from employee e
join all_managers a
on e.city = a.city
and e.employeeid <> a.managerid;
name
jeff
But it you want us to assume that an employee reports to only that manager as listed in the projectid, then here's a modification to ensure that is met:
with all_managers as (
select distinct m.managerid, e.city, e.projectid
from manager m
join employee e
on m.managerid = e.employeeid
)
select e.name
from employee e
join all_managers a
on e.city = a.city
and e.projectid = a.projectid
and e.employeeid <> a.managerid;
View on DB Fiddle
You just need two joins:
one between "managers" and "employees" to gather managers information
one between "managers" and "employees" to gather employees information with respect to the manager's projectid and city.
SELECT employees.name
FROM managers
INNER JOIN employees managers_info
ON managers.mangerid = managers_info.employeeid
INNER JOIN employees
ON managers.projectid = employees.projectid
AND managers_info.employeeid <> employees.employeeid
AND managers_info.city = employees.city

Complex query - retrieve employees working in both two specific departments

I'm trying to figure a way to retrieve employees working in two different departments.
I have 3 simple tables:
employee (employee_id, employee_name)
department (department_id, department_name)
working (eid, did, work_time)
So I have tried to write a SQL query:
select employee_name
from employee, working,department
where eid = employee_id
and did = department_id
and department_name = 'software'
and dname = 'hardware';
But it doesn't work, what is my problem?
The problem is that you are requiring department to be both 'software' and 'hardware'. Also, dname is not a field.
Correcting your query:
select employee_name
from employee, working, department
where eid = employee_id and did = department_id
and (department_name = 'software' or department_name = 'hardware');
But I would prefer this kind of query:
SELECT DISTINCT e.employee_name
FROM employee e
JOIN working w ON w.eid = e.employee_id
JOIN department d ON d.department_id = w.did
WHERE d.department_name IN ('software', 'hardware');
That is to get employees that work in any of the two departments (or both).
If you want only employees that work in both departments, try this:
SELECT e.employee_id, e.employee_name
FROM employee e
JOIN working w ON w.eid = e.employee_id
JOIN department d ON d.department_id = w.did
WHERE d.department_name IN ('software', 'hardware')
GROUP BY e.employee_id HAVING COUNT(DISTINCT d.department_id) = 2;
Would something like this work for you?
SELECT
count(*) as cnt,
employee.employee_name
FROM
employee
JOIN working ON working.eid = employee.employee_id
JOIN department ON department.department_id = working.did
WHERE
department.department_name = 'software' or department.department_name = 'hardware'
GROUP BY employee.employee_name
HAVING cnt > 1
This would count each employee who is linked both software or hardware department. Or you can leave WHERE clause away to get all employees working more than one departments.
What is my problem?
There is no dname column in your tables.
You can simplify the problem as you don't need the department table since the working table contains the department id in the did column.
Then you need to GROUP BY each employee and find those HAVING a COUNT of two DISTINCT department ids:
SELECT MAX(e.employee_name)
FROM employee e
INNER JOIN working w
ON e.employee_id = w.eid
GROUP BY e.employee_id
HAVING COUNT(DISTINCT w.did) = 2
If you want to consider only the software and hardware departments then:
SELECT MAX(e.employee_name)
FROM employee e
INNER JOIN working w
ON e.employee_id = w.eid
INNER JOIN department d
ON w.did = d.department_id
WHERE d.department_name IN ('software', 'hardware')
GROUP BY e.employee_id
HAVING COUNT(DISTINCT w.did) = 2
You can easily obtain employees who work in one specific department:
select *
from Employee e inner join
Working w on e.employee_id = w.eid inner join
Department d on w.did = d.department_id
where d.name = 'software'
Now ambiguity cames. If you want to get all employees work either in software or in hardware:
-- Employees who work at either software or hardware or both departments
select *
from Employee e inner join
Working w on e.employee_id = w.eid inner join
Department d on w.did = d.department_id
where d.name = in ('software', 'hardware')
If you want to get employees who works in both software and hardware departments:
-- Employees who work in both hardware and software deparments simultaneously
select *
from Employee e inner join
Working w on e.employee_id = w.eid inner join
Department d on w.did = d.department_id
where d.name = 'software'
intersect
select *
from Employee e inner join
Working w on e.employee_id = w.eid inner join
Department d on w.did = d.department_id
where d.name = 'hardware'

Highest paid employee + average salary of the departments

An employee belongs to a department (foreign key = D_ID). An employee has a SSN (primary key), name, salary and D_ID.
A department has multiple employees (primary key = ID)
I want a query that returns Department name| Name of Highest Paid Employee of that department | His Salary | Average salary of employees working in the same department.
I know how to select the first part:
SELECT
D.name, E.name, E.salary
FROM
Employee E, Department D
WHERE
salary IN (SELECT MAX(E.salary)
FROM Employee E
GROUP BY E.D_ID)
AND E.D_ID = D.ID
I know also how to select the last part:
SELECT AVG(E.salary)
FROM Employee E
GROUP BY E.D_ID
How do I put these together in a single query?
You can use window functions for that:
select department_name, employee_name, salary, avg_dept_salary
from (
select e.name as employee_name,
d.name as department_name,
e.salary,
max(e.salary) over (partition by d.id) as max_dept_salary,
avg(e.salary) over (partition by d.id) as avg_dept_salary
from Employee E
join Department D on e.d_id = d.id
) t
where salary = max_dept_salary
order by department_name;
The above is standard ANSI SQL and runs on all modern DBMS.
I would do something like this:
SELECT d.name
, e.name
, e.salary
, n.avg_salary
FROM Department d
JOIN ( SELECT m.d_id
, MAX(m.salary) AS max_salary
, AVG(m.salary) AS avg_salary
FROM Employee m
GROUP BY m.d_id
) n
ON n.d_id = d.id
JOIN Employee E
ON e.d_id = d.id
AND e.salary = n.max_salary

I need sql query to merge info from 2 tables

i`m new in SQL and i need a tip. I got 2 tables ( employee and department ),
employee table as E:
id (int), name(nvarchar), gender(nvarchar), departmentID(int), dateofbirth(datetime)
department table as D :
dep_id(int), name(nvarchar), location(nvarchar), boss_id(int)
That`s what i need as output table:
E.id / E.name / D.name / D.location / (and last which i cant get with simple join is:) D.boss.name (not simple boss id but real employee name from E table)
Just simple question for advanced people :-)
Join the table a second time for the boss. (This is assuming that boss_id FK's to Employee)
SELECT
E.Id,
E.Name,
D.Name,
D.Location,
B.Name
FROM Employee E
INNER JOIN Department D on E.DepartmentID = D.Dep_id
INNER JOIN Employee B ON D.Boss_id = B.Id
You can write a query using cte as well:
WITH CTE AS(
Select
e.ID,
e.name,
d.boss_id,
d.Location as DepartmentLocation,
d.name as DepartmentName
From Employee e
INNER JOIN Department d on d.boss_id =E.id
)
Select c.id, c.name, e.name as BossName, c.DepartmentLocation, c.DepartmentName
from cte c
Inner Join Employee e1 on e1.id=c.boss_id
SELECT e.Id, e.Name, d.Name, d.Location,
(
SELECT e2.Name
FROM tblEmployee as e2
WHERE e2.id = d.boss_id
) AS [Boss name]
FROM tblEmployee as e
INNER JOIN tblDepartment as d
ON e.DepartmentID = d.dep_ID

Sub-Query Problem

Department(DepartID,DepName)
Employees(Name,DepartID)
What i need is the Count of Employees in the Department with DepName.
If you are using SQL Server version 2005 or above, here is another possible way of getting employees count by department.
.
SELECT DPT.DepName
, EMP.EmpCount
FROM dbo.Department DPT
CROSS APPLY (
SELECT COUNT(EMP.DepartId) AS EmpCount
FROM dbo.Employees EMP
WHERE EMP.DepartId = DPT.DepartId
) EMP
ORDER BY DPT.DepName
Hope that helps.
Sample test query output:
I'd use an outer join rather than a subquery.
SELECT d.DepName, COUNT(e.Name)
FROM Department d
LEFT JOIN Employees e ON e.DepartID = d.DepartID
GROUP BY d.DepartID, d.DepName
SELECT d.DepName, COUNT(e.Name)
FROM Department d
LEFT JOIN Employees e
ON d.DepartID = e.DepartID
GROUP BY d.DepName
No need for a subquery.
SELECT dep.DepName, COUNT(emp.Name)
FROM DepName dep
LEFT OUTER JOIN Employees emp ON dep.DepartID = emp.DepartID
GROUP BY dep.DepName
SELECT COUNT(DISTINCT Name) FROM
Department AS d, Employees AS e
WHERE d.DepartID=e.DepartID AND d.DepName = '$thename'
And to avoid using a group by and save you a Sort operation in the queryplan:
SELECT
Department.DepName,
(SELECT COUNT(*)
FROM Employees
WHERE Employees.DepartID = Department.DepartID)
FROM
Department