Sub-Query Problem - sql

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

Related

MySQL LEFT JOIN with GROUP BY and WHERE clause query

Tables that look like bellow
How to write SQL Query to read all department names with an employee count salary > 1000, if a department not found in employee we required to show as zero counts in output.
You can use left join and aggregation:
select d.name, count(e.id)
from departments d left join
employees e
on e.department_id = d.id and e.salary >= 10000
group by d.name

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 )

Implementing Join in this query

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.

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

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);

How to add subquery as a column in SQL

How do I add a subquery as a column in my SQL script?
e.g.
Select emp_no, name,gender ,
(select department_name from departments where employees.emp_no = departments.emp_no)
from employees
PS: I'm using oracle 8
Going by the semantics, what I understand is that you want an employee's department name to be shown alongside his/her other information. I would suggest you do a join instead:
Select emp_no, name, gender, department_name
from employees emp, departments dept
where emp.emp_no = dept.emp_no;
That looks reasonably sound, I would suggest some (possible typos) cleaning up: add a comma after "gender" and declare the table names, also set the subquery alias
Select employees.emp_no, employees.name, employees.gender,
(select departments.department_name from departments where employees.emp_no = departments.emp_no) as dept_name
from employees
Alternatively, a nice join would would work too, if the other data is feasible:
Select employees.emp_no, employees.name, employees.gender, departments.department_name
from employees
inner join departments on employees.emp_no = departments.emp_no
left join is the best-practice, and should be faster in performance:
Select e.emp_no, e.name, e.gender , d.department_name
from employees e left join departments d on e.emp_no = d.emp_no;
You seem to be missing comma after gender.
Select emp_no, name,gender ,
(select department_name from departments where employees.emp_no = departments.emp_no) as dept_name from employees
The below is what you need. Just added a comma after gender. This subquery would need to return only one row for each result as well or else an error will be seen.
Select emp_no, name,gender,
(select department_name from departments where employees.emp_no = departments.emp_no)
from employees
This query is your answer but it will work only if there is one column mentioned in that if we use more than one column than it will retrun an error .
"Select employee_id,first_name,
(select department_name,manager_id from departments where employees.department_id = departments.department_id) as new_column
from employees;"
can you try this:
SELECT em.emp_no, em."name",em.gender ,
(SELECTdistinctdp.department_name
FROM departments dp
WHERE em.emp_no = dp.emp_no) my_sub
FROM employees em