Find below the test tables:
SELECT * FROM tbl_emp; // There must be few employee with no dept id (did)
+------+-------+------+
| eid | ename | did |
+------+-------+------+
| 1 | SCOTT | 2 |
| 2 | JAMES | 4 |
| 3 | BOND | 1 |
| 4 | TIGER | 5 |
| 5 | CHIP | 0 |
| 6 | DALE | 0 |
| 7 | MARY | 0 |
+------+-------+------+
SELECT * FROM tbl_dept;// There must be few depts which have no employee.
+-------+-------------+
| dptid | dname |
+-------+-------------+
| 1 | HR |
| 2 | IT |
| 3 | ADMIN |
| 4 | TRAVEL |
| 5 | SALES |
| 6 | FINANCE |
| 7 | ENGINEERING |
+-------+-------------+
I want to list all the employee name from tbl_emp which does not have dept and all the dname from tbl_dept which have no employee in a SINGLE QUERY in following manner:
DESIRED RESULTSET:
-------------------
ename dname
CHIP
DALE
MARY
ADMIN
FINANCE
ENGINEERING
-------------------
All I could do is:
SELECT ename FROM tbl_emp WHERE did NOT IN (SELECT dptid FROM tbl_dept);
and
SELECT dname FROM tbl_dept WHERE dptid NOT IN (SELECT did FROM tbl_emp);
Please help in select both dname and ename and that too in single query.
you can use UNION
SELECT ename, NULL dname
FROM tbl_emp
WHERE did NOT IN (SELECT dptid FROM tbl_dept)
UNION
SELECT NULL ename, dname
FROM tbl_dept
WHERE dptid NOT IN (SELECT did FROM tbl_emp);
SQLFiddle Demo
UPDATE 1
you can also use LEFT JOIN instead of using NOT IN (I'd rather use this one)
SELECT a.ename, b.dname
FROM tbl_emp a
LEFT JOIN tbl_dept b
ON a.did = b.dptid
WHERE b.dptid IS NULL
UNION
SELECT c.ename, d.dname
FROM tbl_dept d
LEFT JOIN tbl_emp c
ON d.dptid = c.did
WHERE c.did IS NULL
SQLFiddle Demo
Related
i have a complaint table
|------------------------|
| cid | desc |
|------------------------|
| 1 | faulty |
| 2 | broken |
| 3 | spoiled |
|------------------------|
and an assignment table
|------------------------------------|
| aid | cid | empid |
|------------------------------------|
| 1 | 1 | 1 |
| 2 | 1 | 5 |
| 3 | 2 | 2 |
| 4 | 2 | |
| 5 | 3 | 2 |
| 6 | 3 | 7 |
|------------------------------------|
each complaint can be assigned to atmost two employees
i need to display a list in the below format
|---------------------------------------------------|
| cid | desc | emp1id | emp2id |
|------------------------|--------------------------|
| 1 | faulty | 1 | 5 |
| 2 | broken | 2 | |
| 3 | spoiled | 2 | 7 |
|------------------------|--------------------------|
i wrote the query like this
select c.cid, c.desc, a1.empid as emp1id, a2.empid as emp2id
from complaint c
left join (
select aid, cid, empid
from assignment aa
where aa.cid = c.cid
limit 0,1
) as a1 on a1.cid = c.cid
left join (
select aid, cid, empid
from assignment ab
where ab.cid = c.cid
limit 1,1
) as a2 on a2.cid = c.cid
but it is not working, i am getting error for c.cid in sub queries. how to do?
This might work? (I don't have mySql installed)
select c.cid,
c.desc,
(
select aid, cid, empid
from assignment aa
where aa.cid = c.cid
limit 0,1
) as emp1id,
(
select aid, cid, empid
from assignment ab
where ab.cid = c.cid
limit 1,1
) as emp2id
from complaint c
How to get name and manager name
+----+-----------+---------+
| id | name | manager |
+----+-----------+---------+
| 1 | bhupendra | 0 |
| 2 | shyam | 1 |
| 3 | ram | 1 |
| 4 | geeta | 2 |
| 5 | sita | 1 |
+----+-----------+---------+
i need result like
+-----------+-----------+
| name | manager |
+-----------+-----------+
| bhupendra | |
| shyam | bhupendra |
| ram | bhupendra |
| geeta | shyam |
| sita | bhupendra |
+-----------+-----------+
You could self-join the id column on the manager column:
SELECT e.name AS name, m.name AS manager
FROM employee e
LEFT JOIN employee m ON m.id = e.manager
You should use the same table twice using alias
select a.name, b.name as manager
from my_table a
left join my_table b on a.manager = b.id
Check this out
with recursive cte (id, name, parent_id) as (
select id,
name,
manager
from employee
union all
select p.id,
p.name,
p.manager
from employee e
inner join cte
on p.manager = cte.id
)
select * from cte;
I'm working with a database structure similar to this one: http://dev.mysql.com/doc/employee/en/sakila-structure.html
Table: employees
Table with information about each employee.
+---------+----------+
| emp_no* | emp_name |
+---------+----------+
| emp1 | John |
| emp2 | Mike |
| emp3 | Rob |
| emp4 | Kim |
+---------+----------+
Table: departments
Table with information about the departments of the company.
+----------+-----------+
| dept_no* | dept_name |
+----------+-----------+
| 1 | Dep 1 |
| 2 | Dep 2 |
| 3 | Dep 3 |
| 4 | Dep 4 |
| 5 | Dep 5 |
+----------+-----------+
JUNCTION TABLE: emp_dept
primary key: [ emp_no, from_date ]
Table to keep track of the departments where an employee had worked before or is working right now.
+---------+----------+------------+------------+
| emp_no* | dept_no | from_date* | to_date |
+---------+----------+------------+------------+
| emp1 | 1 | 2010-01-01 | 2010-12-31 |
| emp2 | 2 | 2010-01-01 | 2013-10-31 |
| emp1 | 4 | 2010-12-31 | 2012-06-14 |
| emp3 | 3 | 2010-01-01 | 2011-08-14 |
| emp4 | 1 | 2010-01-01 | 2014-11-14 |
| emp2 | 5 | 2013-10-31 | 2014-11-14 |
| emp1 | 3 | 2012-06-14 | 2014-11-17 |
| emp3 | 1 | 2011-08-14 | 2013-07-20 |
| emp3 | 4 | 2013-07-20 | 2014-11-14 |
+---------+----------+------------+------------+
THE EXPECTED TABLE:
¿How could I join only the latest record for each employee from the junction table (emp_dept) to my employee table and get a table like the one below?
+---------+----------+--------+
| emp_no* | emp_name | dep_no |
+---------+----------+--------+
| emp1 | John | 3 |
| emp2 | Mike | 5 |
| emp3 | Rob | 4 |
| emp4 | Kim | 1 |
+---------+----------+--------+
Assuming emp_dept.Emp_no is the relation between employees.Emp_no
Select * from
employees e
join emp_dept ed on e.emp_no = ed.emp_no
and from_date = (Select Max(from_date)
from emp_dept ed2 where ed2.emp_no = e.emp_no)
Create a query that only delivers the last Dept for each Employee, then add that to your main query in a JOIN or a CROSS APPLY
... tables with joins etc ...
CROSS APPLY
(
SELECT TOP 1 employee , dept_no FROM emp_dept
WHERE employee = !EMP FROM MAIN TABLE!
ORDER BY to_date DESC
) AS last_dept
where !EMP FROM MAIN TABLE! is your employee value from the tables before the CROSS APPLY
(Post your full query so far, for a more complete answer)
you can get the maximum date in a subquery and join with it.
looks like you have a typo in the emp_dept table entries, the emp_no is not matching with employees table.
In case a employee is currently working in deparment, does to_date will be NULL?
In such as case, you need to handle it in the sub query.
SELECT e.emp_no, e.emp_name, ED.dept_no
FROM
(
SELECT emp_no, max(to_date) as maxDate
FROM emp_dept
group by emp_no)T
JOIN employee e
ON T.emp_no = e.emp_no
JOIN emp_dept ED
on T.maxDate = ED.t_date
AND ED.emp_no = T.emp_no
EDIT VERSION
EMPLOYEE TABLE
|ID | employee_id | Name |
| 1 | 123 | John Richard |
| 2 | 554 | Daniel Domingo |
educational background
|ID | employee_id | School/institute | date graduated |
| 1 | 123 | highschool | 2007 |
| 2 | 123 | college | 2011 |
| 3 | 554 | college | 2010 |
| 4 | 554 | masteral | 2013 |
job title
|ID | employee_id | Job description |
| 1 | 123 | Free lancer |
| 2 | 554 | admin assistant |
i need to select the latest date info of the employee's educational background
the result would be
result query
|ID | employee_id | Name | Job title | year_graduated | school_institute |
| 1 | 123 | John Richard | Free Lancer | 2011 | college |
| 2 | 554 | Daniel Domingo | Admin Assistant | 2013 | masteral |
Try this:
SELECT *
FROM (SELECT * FROM tableA ORDER BY employee_id, date_graduated DESC) A
GROUP BY employee_id
OR
SELECT a.*
FROM tableA a
INNER JOIN (SELECT employee_id, MAX(date_graduated) maxDate
FROM tableA GROUP BY employee_id
) b ON a.employee_id = b.employee_id AND a.date_graduated = b.maxDate
SELECT employee_id ,MAX([date graduated]) FROM Table GROUP BY [employee_id]
The result is
employee_id | date graduated
----------------------------
123 | 2011
554 | 2013
Subquery will return the maximum date for every employee, you should then join this subquery with your table to return the full row:
SELECT yourtable.*
FROM
yourtable INNER JOIN (SELECT employee_id, MAX(`date graduated`) max_date
FROM yourtable
GROUP BY employee_id) m
ON yourtable.employee_id = m.employee_id
AND yourtable.`date graduated` = m.max_date
for employee 123
SELECT * FROM `your_table`
WHERE employee_id=123
ORDER BY date_graduated DESC LIMIT 1
for employee 554
SELECT * FROM `your_table`
WHERE employee_id=554
ORDER BY date_graduated DESC LIMIT 1
SELECT *
FROM t
GROUP BY employee_id
HAVING date_graduated=max(date graduated)
and you'll get the desired result
i have 3 tables, the employee table, educational background and job_title,
i need to join the 3 tables and select the latest year the employee is graduated. the result query i need is listed below.
EMPLOYEE TABLE
|ID | employee_id | Name |
| 1 | 123 | Jewel Brin |
| 2 | 554 | Donna Ferry |
| 3 | 853 | Ricky David |
educational background
|ID | employee_id | School/level | date graduated |
| 1 | 123 | highschool | 2007 |
| 2 | 123 | college | 2011 |
| 3 | 554 | college | 2010 |
| 4 | 554 | masteral | 2013 |
job title
|ID | employee_id | Job description |
| 1 | 123 | Free lancer |
| 2 | 554 | admin assistant |
| 3 | 853 | Support Admin |
i need to select the latest date info of the employee's educational background
the result would be:
result query
|ID | employee_id | Name | Job title | year_graduated | school_institute |
| 1 | 123 | Jewel Brin | Free Lancer | 2011 | college |
| 2 | 554 | Donna Ferry | Admin Assistant | 2013 | masteral |
| 3 | 853 | Ricky David | Support Admin | Null | Null
Forgot to mention, this is MySQL :)
SELECT e.employee_id, Name, `Job description` AS `Job title`, year_graduated, school_institute
FROM `employee` e
INNER JOIN job_title j ON j.employee_id = e.employee_id
LEFT JOIN (SELECT ID, `School/level` AS school_institute, employee_id, `date graduated` AS year_graduated FROM `educational background` b
INNER JOIN (
SELECT ID, MAX(`date graduated`) AS max_date FROM `educational background` GROUP BY employee_id
) b2
ON b2.max_date = b.year_graduated AND b2.ID = b.ID
) bb ON bb.employee_id = e.employee_id
In SQL Server :-
Select *
from
(
Select e.ID,e.employee_ID,e.Name,
b.Level,j.[Job description],
rn = row_number()
over (partition by e.Employee_ID order by [date graduated] desc)
From Employee e
left join Background b
on e.Employee_ID = b.Employee_ID
left join Jobtitle j
on j.Employee_ID = b.Employee_ID
)a
where a.rn=1
SQL FIDDLE
For Mysql you can try this
SELECT DISTINCT
e.employee_id,
e.Name,
j.Job_description,
eb.year_graduated,
eb.level
FROM
EMPLOYEE e
LEFT JOIN
(SELECT
*,
MAX(t.date_graduated) year_graduated
FROM
(SELECT * FROM Background ORDER BY date_graduated DESC) t
GROUP BY employee_id) eb
ON (e.employee_id = eb.employee_id)
LEFT JOIN JobTitle j
ON (e.employee_id = j.employee_id)
See Fiddle Demo