我有3个表,persons
,companies
和tasks
。
人们在不同的公司做不同的任务。
我想要的是所有人员表的列表,他们在任务中的最后一项任务以及执行该任务时公司的名称。最近的任务可能是最新的task_date或更高的id.tasks,它具有相同的结果。
表persons
:
| id | Name |
| 1 | Person 1 |
| 2 | Person 2 |
| 3 | Person 3 |
| 4 | Person 4 |
表companies
:
—————————————————————
| id | company |
—————————————————————
| 1 | Company 1 |
| 2 | Company 2 |
| 3 | Company 3 |
| 4 | Company 4 |
—————————————————————
表tasks
:
————————————————————————————————————————————————————————————————————
| id | task_name | task_date | id_persons | id_companies |
————————————————————————————————————————————————————————————————————
| 1 | Task 1 | 2015-01-02 | 1 | 3 |
| 2 | Task 2 | 2016-03-02 | 1 | 4 |
| 3 | Task 3 | 2016-06-04 | 2 | 1 |
| 4 | Task 4 | 2016-01-03 | 4 | 2 |
结果应该是这样的表格:
| persons.id | persons.name | company.name |
| 1 | Person 1 | Company 4 |
| 2 | Person 2 | Company 1 |
| 3 | Person 3 | |
| 4 | Person 4 | Company 2 |
——————————————————————————————————————————————————
我有这个问题:
SELECT t.id id_t, t.id_companies t_id_companies, c.company_name , p.*
FROM persons p
INNER JOIN tasks t ON t.id_persons = p.id
INNER JOIN
(
SELECT id_persons, MAX(id) max_id
FROM tasks
GROUP BY id_persons
) b ON t.id_persons = b.id_persons AND t.id = b.max_id
INNER JOIN companies c ON c.id = t.companies.id
WHERE p.deleted = 0
我认为结果还可以,但有一些失踪者,因为INNER JOIN
的使用(我有没有任何相关任务的人)。我试图将INNER JOIN
更改为LEFT JOIN
,但结果不合适。
感谢任何帮助。
答案 0 :(得分:1)
您应该做的是将最新的任务/公司数据设置为内联视图,然后从人员表中进行左连接。
SELECT *
FROM persons p
LEFT JOIN (
SELECT * FROM tasks t
INNER JOIN companies c ON c.id = t.companies.id
WHERE t.id IN (SELECT max(id) FROM tasks GROUP BY id_persons)
) combined_tasks
ON p.id = combined_tasks.id
WHERE p.deleted = 0
答案 1 :(得分:1)
解决方案位于LEFT JOIN
,但您需要先加入子查询,然后才能加入tasks
表,否则会得到太多结果(我还修复了查询中的一些拼写错误) ):
SELECT p.id persons_id, p.name persons_name, c.company_name
FROM persons p
LEFT JOIN
(
SELECT id_persons, MAX(id) max_id
FROM tasks
GROUP BY id_persons
) b ON p.id = b.id_persons
LEFT JOIN tasks t ON t.id_persons = p.id AND t.id = b.max_id
LEFT JOIN companies c ON c.id = t.id_companies
WHERE p.deleted = 0
ORDER BY 1
输出与您在问题中列出的完全相同:
| id | Name | company_name |
|----|----------|--------------|
| 1 | Person 1 | Company 4 |
| 2 | Person 2 | Company 1 |
| 3 | Person 3 | (null) |
| 4 | Person 4 | Company 2 |
这是fiddle
答案 2 :(得分:0)
试试这个:
SELECT p.id, p.name, c.name
FROM persons p
LEFT JOIN ((
SELECT id_persons, id_companies, MAX(id) max_id
FROM tasks
GROUP BY id_persons, id_companies
) t INNER JOIN companies c ON c.id = t.companies.id)
ON t.id_persons = p.id
WHERE p.deleted = 0
答案 3 :(得分:0)
鉴于您的查询,我只会做一个简单的修改:
SELECT t.id id_t, t.id_companies t_id_companies, c.company_name , p.*
FROM persons p LEFT JOIN
tasks t
ON t.id_persons = p.id LEFT JOIN
(SELECT id_persons, MAX(id) as max_id
FROM tasks
GROUP BY id_persons
) b
ON t.id_persons = b.id_persons AND t.id = b.max_id LEFT JOIN
companies c
ON c.id = t.companies.id
WHERE p.deleted = 0;
换句话说,所有JOIN
都应为LEFT JOIN
s。这是您查询所需的唯一更改。
答案 4 :(得分:0)
SELECT p.*, combined_tasks.companyname
FROM person p
LEFT JOIN (
SELECT t.personid as personid, c.name as companyname FROM task t
INNER JOIN company c ON c.id = t.companyid
WHERE t.id IN (SELECT max(id) FROM task GROUP BY personid)
) combined_tasks
ON p.id = combined_tasks.personid