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
Related
Some help will be greatly appreciated. I am trying to find the last date of most recent promotion of all employees from a dataset. A sample of the dataset is as below.
DATASET -
mysql> select * from emp;
+----+-------+-----------+------------+
| id | empid | title | startdate |
+----+-------+-----------+------------+
| 1 | 111 | Associate | 2017-11-01 |
| 2 | 222 | ED | 2017-11-01 |
| 3 | 111 | Associate | 2017-12-01 |
| 4 | 222 | MD | 2017-12-01 |
| 5 | 111 | VP | 2018-01-01 |
| 6 | 222 | MD | 2018-01-01 |
| 7 | 111 | VP | 2018-02-01 |
| 8 | 222 | MD | 2018-02-01 |
+----+-------+-----------+------------+
The output I want -
+-------+-----------+----------------+
| empid | title | min(startdate) |
+-------+-----------+----------------+
| 222 | MD | 2017-12-01 |
| 111 | VP | 2018-01-01 |
+-------+-----------+----------------+
I tried this SQL -
mysql> select empid, title, min(startdate)
from ( select * from emp ) x
group by title, empid
order by empid desc;
It outputs all groups, like this -
+-------+-----------+----------------+
| empid | title | min(startdate) |
+-------+-----------+----------------+
| 222 | MD | 2017-12-01 |
| 222 | ED | 2017-11-01 |
| 111 | Associate | 2017-11-01 |
| 111 | VP | 2018-01-01 |
+-------+-----------+----------------+
You can filter on the latest title per employee with a correlated subquery, and then aggregate:
select empid, title, min(startdate)
from emp e
where e.title = (
select e1.title
from emp e1
where e1.empid = e.empid
order by startdate desc
limit 1
)
group by empid, title
order by empid desc
Demo on DB Fiddle:
empid | title | min(startdate)
----: | :---- | :-------------
222 | MD | 2017-12-01
111 | VP | 2018-01-01
Take the empid and the max(startdate) ONLY, as a subquery and join it back to the main table:
SELECT *
FROM emp e
INNER JOIN
(SELECT empid, Max(startdate) recentpromo FROM emp GROUP BY empid) x
ON x.empid = e.empid AND x.recentpromo = e.startdate
If you're on mysql8 you could use ROW_NUMBER for this as an alternative. If an employee is promoted twice on the same day this will pick up both records, though I think that unlikely to occur
Edit, so we can extend this another level:
SELECT
em.empid,
em.title,
min(em.startdate) as
FROM
emp em
INNER JOIN
(
SELECT e.empid, e.title
FROM emp e
INNER JOIN
(SELECT empid, Max(startdate) recentpromo FROM emp GROUP BY empid) x
ON x.empid = e.empid AND x.recentpromo = e.startdate
) frpt --find recent promo title
ON
em.empid = frpt.empid AND
em.title = frpt.title
GROUP BY
em.empid, em.title
I Have a table called EMPLOYEE
| employee_id | name | supervisor_id |
| 123 | Ace Ven | NULL |
| 124 | Ben Agent | 123 |
| 125 | Sam Marks | 123 |
| 126 | Bob Teabag | 125 |
| 127 | Matthew Smith | 125 |
| 128 | Toby McQuire | 123 |
I am trying to find the supervisors and list the amount of employees they have. as you can see the supervisor_id is the same as employee_id. Should come out like this
name | total_employees |
Ace Ven | 3 |
Sam Marks | 2 |
I tried
SELECT supervisor_id, name, count(supervisor_id) AS total_employees FROM EMPLOYEE GROUP BY name HAVING (total_employees > 0);
which didn't work at all (sorry about the format, can't seem to get it to work).
Subquery counts how many records/employees are for each supervisor_id, then this result simply joined table again for retrieving their names:
select your_table.name, t.total_employees from your_table
inner join
(select supervisor_id, count(*) as total_employees from your_table where supervisor_id is not null group by supervisor_id) t
on your_table.employee_id = t.supervisor_id
A simple join will suffice...
Select x.name
, count(*) total
from employee x
join employee y
on y.supervisor_id = x.employee_id
group
by x.employee_id;
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
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
having this record in MySQL database:
emp_name | team | start date | level |
----------+----------+---------------+--------
john | alpha | 2013-may-28 | 1 |
john | beta | 2013-apr-05 | 3 |
john | beta | 2013-jan-03 | 1 |
john | gamma | 2012-dec-04 | 3 |
john | gamma | 2012-sep-28 | 2 |
john | gamma | 2012-sep-11 | 1 |
john | beta | 2012-jul-17 | 3 |
john | beta | 2012-may-03 | 1 |
john | alpha | 2012-feb-12 | 3 |
john | alpha | 2012-jan-01 | 1 |
how should i know that john is a member of team:
| from | to
---------------------------------
alpha | 2012-jan-01 | 2012-may-03
beta | 2012-may-03 | 2012-sep-11
gamma | 2012-sep-11 | 2013-jan-03
beta | 2013-jan-03 | 2013-may-28
alpha | 2013-may-28 | now
i don't know what to put in my WHERE clause to achieve this..i only need to have the team name, the date he started on that team, and the end date on that team..level column in not important..
SELECT emp_name, team, min(start_date) start_date, end_date
FROM (
SELECT t1.emp_name, t1.team, t1.start_date, min(t2.start_date) end_date
FROM table1 t1
LEFT JOIN table1 t2
ON t1.emp_name = t2.emp_name
AND t1.team != t2.team
AND t1.start_date < t2.start_date
GROUP BY t1.emp_name, t1.team, t1.start_date) t3
GROUP BY emp_name, team, end_date
ORDER BY start_date
Demo: SQL Fiddle
SELECT emp_name,min(startdate) as startdate,max(ldate) as enddate,team
FROM (
SELECT emp_name,startdate ,team,
#n:=if(#lastteam=team,#n,#n+1) rank,
#l:=if(#enddate=startdate,startdate,#enddate) ldate,
#lastteam:=team, #enddate:=startdate
FROM t, (SELECT #n := 0,#lastteam:='',#enddate:='') n
ORDER BY startdate desc
) m
GROUP BY rank
SQL FIDDLE here: http://www.sqlfiddle.com/#!2/860fd/20