list pair of employees that work in same department - sql

in oracle SQL how can I list pair of employees that work in same department ... my employee table as follow:
employeeid department
101 2
102 2
103 3
104 3
105 4

You can get all employees in departments that have multiple employees by
SELECT * FROM employees
WHERE department IN
(
SELECT department
FROM employees
GROUP BY department
HAVING COUNT(*) > 1
)
Or use LISTAGG to show the IDs in a list:
SELECT
department,
LISTAGG(employeeid, ', ') AS EmployeeList
FROM employees
GROUP BY department
HAVING COUNT(*) > 1

If your table is called t, you can "list" the pairs of employees who work in the same department with a self-join, like this:
select t1.employeeid as employee1, t2.employeeid as employee2, department
from t t1 join t t2 using (department)
where t1.employeeid < t2.employeeid
Fair warning: for departments with a large number of employees, the number of pairs grows asymptotically like 1/2 times the square of the number of employees in that department, so you may get a very large number of rows on a "real" input table.
If needed, you can sort the results as needed, for example add this line:
order by department, employee1, employee2

Related

SQL select groups where values are exclusively in a list

Given a table with two columns, department and employee, where every employee belongs to 1 department.
Given a list of employee ids, how do I select departments where all employees are in the list?
Department
Employee
finance
1
finance
2
marketing
3
marketing
4
IT
5
IT
6
given (2,3,4,5,6), returns ('marketing', 'IT')
(Note: DB flavor does not matter to me, you may use standard or DB-specific SQL)
Put your input id's into a table, join to the existing table, and check counts between input and the existing employees. If they match, output.
Change this to whatever RDBMS you're using
CREATE TEMP TABLE input_vals (id int);
insert into input_vals
values
(2),
(3),
(4),
(5),
(6);
with cte_joins AS (
select ot.department,
count(ot.employee) AS employee_count1,
sum(case when iv.id is not null then 1 else 0 end) AS employee_count2
from orig_table ot
left join input_vals iv
on ot.employee = iv.id
group by ot.department
)
select department
from cte_joins
where employee_count1 = employee_count2
You can use a couple of derived tables - one to get the count of employees in each department and one to get the count of employees in each department limited by your list of employees. Return the ones that match.
select
distinct full_list.department
from (
select
department,
count (*) as cnt
from
<your table>
group by department) full_list
inner join (
select
department,
count (*) as cnt
from
<your table>
group by department
where
employee in (2,3,4,5,6)
) limited_list
on full_list.department = limited_list.department
and full_list.cnt = limited_list.cnt
-- departments
select department from t where employee in (2,3,4,5,6);
-- departments containing extra persons
select department from t
where department in (select department from t where employee in (2,3,4,5,6))
and employee not in (2,3,4,5,6);
--- departments, employees from the list, with no extra
select department from t
where employee in (2,3,4,5,6) and department not in (
select department from t
where department in (
select department from t where employee in (2,3,4,5,6)
) and employee not in (2,3,4,5,6)
)
Assume you employee list is captured as a column in a table. Since you didn't provide any detail on the tool set you are using.
Something like this is a common pattern, depending on your dbms there's other more simple syntax.
select distinct
de.department
from department_employee de
where not exists
( select 1
from department_employee de2
where not exists
( select 1
from employee_list el
where de2.employee = el.employee
)
and de.department = de2.department
);

SSMS Count with HAVING - SQL

I'm trying to count the number of Departments in a database where there are exaclty 6 employees in each Department.
I've written the query below, but it returns the rows with the Departments where there are 6 employees.
But what I'd like is the TOTAL NUMBER of ROWS where each Department has 6 employees.
Does anyone know how I can modify this query to give me a total number, please?
TIA
select count(Department)
--Department as [Department Name]
from HumanResources.vEmployeeDepartment
GROUP BY Department
HAVING count(Department) = 6
You can wrap your query with another count statement to count the number of departments returned by the inner query:
select COUNT(*) from
(
select Department as cnt
from HumanResources.vEmployeeDepartment
GROUP BY Department
HAVING count(Department) = 6
) as t

Creating dynamic query which has also has a sub-query

I use two queries in SQL Server, which I would like to combine and create a single query. Tried few options but of not much success.
Query 1
select emp_id, name, age
from employee
where age > 50
Query 2
select dept_id, dept_name
from department
where emp_id = 'COMPANY.ID' + emp_id
The issue in combining the two queries is, though query 1 can return multiple rows, I can't use a subquery to directly use emp_id from query 1 in query 2 since the emp_id in query 2 has a prefix of 'COMPANY.ID.'+emp_id. Any suggestions?
COMPANY.ID is a constant that gets prefixed to emp_id before saving it in department table.
Example employee table
emp_id name age
-----------------------------
123 John 45
345 Susan 34
789 Pat 66
Example department table
emp_id dept_id dept_name
-----------------------------------------------------------------------
COMPANY.ID.123 123 Accounting
COMPANY.ID.345 123 Accounting
Hope these examples help understand my dataset
I understand that you are trying to pull out the departments that have at least one employee older than 50.
One solution would be to use an EXISTS condition with a correlated subquery:
SELECT dept_id, dept_name
FROM department d
WHERE EXISTS (
SELECT 1
FROM employee e
WHERE
CONCAT('COMPANY.ID.', e.emp_id) = d.emp_id
AND e.age > 50
)
Demo on DB Fiddle
Is this what you want as
Query 2 is totally wrong and would never match instead would have used like %CompanyId%
select distinct dept_id, dept_name
from
department where empid IN (
select emp_id from
employee where age > 50 and empid
like '%CompanyId%' )
You can combine the two tables using join
SELECT d.dept_id, d.dept_name
FROM department d
INNER JOIN employee e
ON CONCAT('COMPANY.ID.', e.emp_id) = d.emp_id
WHERE e.age > 50

Find department with maximum number of employees in Oracle SQL

I have these two tables and I need to find the department name with maximum number of employees.
The other solutions were not for Oracle, so I'm posting this question. Also, it would be really helpful if the query can be explained thoroughly as I'm finding it hard to visualise it.
EMPLOYEE
EMPNO EMPNAME MANAGER SALARY DEPT_NO
1 Puja 6 30000 2
2 Purabi 1 15000 3
3 Barun 6 23000 2
4 Sudha 1 20000 1
5 Amal 2 20000 1
6 Rakesh 3 30000 4
DEPARTMENT
Dept_No Dept_Name Location
1 Production LaneA
2 Marketing LaneB
3 Sales LaneC
4 HR LaneD
So far I could manage getting the highest number of employees. So I was thinking if somehow I can write another sub-query where I count the employees in the departments again and compare them to the max_num_emp that I calculated in the first query.
This is the query which retrieves the maximum number of employees. It does not return the dept_no.
select count(dept_no)
from employee
group by dept_no
order by count(dept_no) desc
fetch first row only;
Expected output
DEPT_NAME
Production
Marketing
I can also add the dept_no column in the query, then I will have to somehow find out how to get the max and that was somehow giving me errors because the query was violating some rules. I had actually tried doing max(above query).
So I thought of just getting the maximum employee count and then determine all departments which have those many employees and display their name.
You have a working query which you need to join to the table department:
select d.Dept_Name
from department d inner join (
select dept_no
from employee
group by dept_no
order by count(*) desc
fetch first row only
) t
on t.dept_no = d.dept_no
Edit
Try this (I cannot try it):
select d.dept_name
from department d inner join (
select x.dept_no from (
select dept_no, rank() over (order by count(*) desc) rn
from employee
group by dept_no
order by count(dept_no) desc
) x
where x.rn = 1
) t
on t.dept_no = d.dept_no
You may have used FETCH..FIRST syntax using WITH TIES instead of ONLY.
SELECT d.dept_name
FROM department d
JOIN employee e ON d.dept_no = e.dept_no
GROUP BY d.dept_name
ORDER BY COUNT(*)
DESC FETCH FIRST 1 ROW WITH TIES ;
Demo
If you are not looking for duplicates, then:
select d.dept_name, count(*)
from department d join
employee e
on d.dept_no = e.dept_no
group by d.dept_no, d.dept_name
order by count(dept_no) desc
fetch first row only;

Oracle Grouping and Duplicate Checking

I've been scratching my head on this one.
This question got me closer but my situation is a little more complex.
How do I find duplicate values in a table in Oracle?
Suppose I have a table EMPLOYEE and I want to know which employees work in multiple departments. My table has the employee id, and department they work in. When an employee works in multiple departments, their employee id will be listed as multiple records. I don't want to just count the employees that are listed twice. I need to know how many work in this list of departments vs this list of departments.
So for example if my table is:
Employee ID | Department
1 Accounting
1 Marketing
2 Accounting
3 Finance
4 Programming
And Department List A is
Accounting
Finance
And Department List B is
Marketing
Programming
Then the results of the query would be
Employee ID | Department
1 Accounting
1 Marketing
or
Employee ID | Count(Department)
1 2
since employee 1 works in a department from List A and List B.
I would approach this with a mapping:
with mapping as (
select 'Accounting' as department, 'A' as grouping from dual union all
select 'Finance' as department, 'A' as grouping from dual union all
select 'Marketing' as department, 'B' as grouping from dual union all
select 'Programming' as department, 'B' as grouping from dual
)
select employeeid, count(distinct m.grouping)
from t join
mapping m
on t.department = m.department
group by employeeid;
Note: you may want to store this information in another table or as an attribute in the Departments table.
If you want solo departments to map to themselves:
select t.employeeid, count(distinct coalesce(m.grouping, t.department))
from t join
mapping m
on t.department = m.department
group by t.employeeid;
If you want other departments not in the table to be grouped together:
select t.employeeid, count(distinct coalesce(m.grouping, 'UNKNOWN MAPPING'))
from t join
mapping m
on t.department = m.department
group by t.employeeid;
If I understand what you're after, you can use conditional aggregation in a HAVING clause for this:
SELECT Employee_ID, COUNT(DISTINCT Department) AS Dept_Count
FROM YourTable
GROUP BY Employee_ID
HAVING MAX(CASE WHEN Department IN ('Accounting','Finance') THEN 1 ELSE 0 END) = 1
AND MAX(CASE WHEN Department IN ('Marketing','Programming') THEN 1 ELSE 0 END) = 1