Implementing Join in this query - sql

I currently have a query to find if one employee is working on more than one assignment, and returns the names of the employees.
SELECT Eid, Count(Eid),
(SELECT Ename from Employee where Employee.Eid = Assignment.Eid) as EName
FROM Assignment
GROUP BY Eid HAVING Count(Eid) > 1;
Employee table has EID, and EName field. Assignment has EID and AssignmentNum.
Currently it works, but I think it can be written better with Inner Join, but I can't seem to compose a query with join that works. Any help would be appreciated.

You would just do:
SELECT a.Eid, Count(*), e.EName
FROM Assignment a JOIN
Employee e
ON e.Eid = a.Eid
GROUP BY a.Eid, e.name
HAVING Count(*) > 1;

SELECT e.ename, a.Eid, Count(a.Eid),
from Employee
Inner join assignment as a on e.Eid = a.Eid
GROUP BY a.Eid
HAVING Count(a.Eid) > 1;
You had the necessary join logic within the subquery.

Related

How to get result if exactly one match inner join

How can I write a query to join two tables and return result if exactly one match in there. I have to discard results if zero match and more than one match.
All I am looking for is to extend the INNER JOIN. Let me just get to the point. I have two tables Dept & Emp. One Dept can have multiple Emp's & not the other way around.
Table Dept
Table Emp
I need to JOIN it on Dept_id
Expected Results
You can join with a not exists condition:
select d.*, e.emp_id, e.emp_name
from dept d
inner join emp e
on d.dept_id = e.dept_id
and not exists (
select 1
from emp e1
where e1.dept_id = d.dept_id and e1.emp_id != e.emp_id
)
One alternative to existing solutions can be one using analytics (window functions),
instead of joining twice:
select dept_id, dept_name, emp_id, emp_name
from
(
SELECT
d.Dept_id, d.Dept_name, e.Emp_id, e.Emp_Name,
count(*) over (partition by d.dept_id) cnt1
FROM d
INNER JOIN e
ON d.Dept_id = e.Dept_id
) where cnt = 1;
You could use a subquery for group by dept_id haing count = 1
select t.dept_id, dept.dept_name, emp.Emp_name
from (
select dept_id
from emp
group by dept_id
having count(*) = 1
) t
INNER JOIN dept on t.dept_id = dept.dept_id
INNER JOIN emp ON t.dept_id = emp.dept_id
You can phrase this as an aggregation query in Oracle:
select d.dept_id, d.dept_name,
max(e.emp_id) as emp_id,
max(e.emp_name) as emp_name
from dept d inner join
emp e
using (dept_id)
group by d.dept_id, d.dept_name
having count(*) = 1;
This works because if there is only one match, then max() returns the value from the one row.
Also, try below query;
SELECT a.depid dept_id,dept_name,emp_id,emp_name
FROM
(SELECT case WHEN count(*)=1 THEN dept_id END depid FROM emp GROUP BY dept_id) a INNER JOIN emp ON depid=dept_id
INNER JOIN dept b ON a.depid = b.dept_id
WHERE depid IS NOT NULL
Another way would be
select d.dept_id, d.dept_name, e.emp_name
from emp e
join dept d on d.dept_id = e.dept_id
where e.dept_id in
( select dept_id from emp group by dept_id having count(*) = 1 )

How to get all departments with Employee number

I have an EmployeeDepartmetn juction table like this. I have all the departments in Depeartment table and employees in Employee table..
I want to get departments for an particular employee along with the all the departments available in depeartment table.
It should be like Select DepartmentId, DepartmentName, EmployeeID from Query.
Main criteria here is, Need to display NULL if the employee dont have that department. I am confused here...please help.
Please give Linq Query
Thanks in Advance
Put criteria in your left join:
Select distinct a.DeptID, b.DepartmentName, b.EmployeeID
From Department a
left join EmployeeDepartment b
on a.DeptID = b.DeptID and b.EmployeeID = 1 --insert employee ID here
It will show all departments (even those with no employees), then show the employee ID you chose in the third column only if that employee is assigned there.
You can do this with conditional aggregation:
select DeptId,
max(case when EmployeeId = 1 then EmployeeId end) as EmployeeId
from EmployeeDepartment ed
group by DeptId;
EDIT:
If you have a departments table as well:
select d.deptid, d.name, ed.employeeid
from Departments d left join
EmployeeDepartment ed
on d.deptid = ed.deptid and
ed.employeeid = 1;

"Double Group By" in Oracle SQL?

As I was learning SQL statements I encountered one example (regarding the demo SCOTT database), I have no idea how to solve.
In which department(s) are all salgrades present?
My most promising approach is to group all salgrades and departments in the joined tables emp, dept and salgrade:
SELECT s.grade AS "Salgrade",
d.dname AS "Department ID"
FROM emp e INNER JOIN dept d ON(e.deptno = d.deptno)
INNER JOIN salgrade s ON(e.sal BETWEEN s.losal AND s.hisal)
GROUP BY d.dname, s.grade
Executing this gives me the following results:
If I could group this another time by department, COUNT(*) could give me the number of different salgrades per department. Then I could compare this number (with HAVING) to the following subselect:
(SELECT COUNT(*)
FROM salgrade)
Is there any possibility to group a table which already contains
GROUP BY?
Is there another (better) approach I could use?
I am using an apex-oracle-server with "Application Express 4.2.4.00.07"
Minor change from your version, by removing the grouping inside, and this version, first generates, salgrade and department of all employees, and then doing a grouping outside, counting distinct salary grades.
SELECT Department_ID
FROM
(
SELECT s.grade AS Salgrade,
d.dname AS Department_ID
FROM emp e
INNER JOIN dept d ON(e.deptno = d.deptno)
INNER JOIN salgrade s ON(e.sal BETWEEN s.losal AND s.hisal)
)
GROUP BY Department_ID
HAVING COUNT(distinct Salgrade) = ( SELECT count(1) FROM salgrade);
I found an even easier solution now:
SELECT d.dname
FROM emp e INNER JOIN dept d ON(e.deptno = d.deptno)
INNER JOIN salgrade s ON(e.sal BETWEEN s.losal AND s.hisal)
GROUP BY d.dname
HAVING COUNT(DISTINCT s.grade) = (SELECT COUNT(*) FROM salgrade);
Simple way would be - if performance is not a problem.
SELECT
COUNT(DISTINCT [Salgrade]) AS [COUNT]
,[Department ID]
FROM (SELECT s.grade AS "Salgrade",
d.dname AS "Department ID"
FROM emp e INNER JOIN dept d ON(e.deptno = d.deptno)
INNER JOIN salgrade s ON(e.sal BETWEEN s.losal AND s.hisal)
GROUP BY d.dname, s.grade) DEPT_SALE
GROUP BY [Department ID]
There could be better solutions though if we know more of your base tables - emp & salegrade

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

Using MAX aggregate between two tables

I have two tables, employer and position:
Employer
eID
eName
Position
eID
salary
I need to match my eID between the two tables, determine what the max salary is, and print only the eName. Any suggestions as to how I can do this? I have tried multiple ways, but nothing seems to work.
I am not sure where to put in the max(salary) function:
select eName
from employer, position
where employer.eID = position.eID
To get the name(s) of the people with the highest salary...
Using a JOIN:
SELECT e.name
FROM EMPLOYER e
JOIN POSITION x ON x.eid = e.eid
JOIN (SELECT MAX(salary) AS max_salary
FROM POSITION) y ON y.max_salary = x.salary
Using a subquery:
SELECT e.name
FROM EMPLOYER e
JOIN POSITION p ON p.eid = e.eid
WHERE p.salary = (SELECT MAX(salary)
FROM POSITION)
select e.ename,p.salary
from employer e ,position p
where p.salary=(select max(salary) from position)
and e.eid=p.eid
Join the tables, sort, and get the first one:
select top 1 e.eName, p.salary
from Employer e
inner join Position p on p.eID = e.eID
order by p.salary desc
(This returns the salary also, but you can of course remove it if you really don't want it.)