在第二张桌子上加入3张桌子,LIMIT 1

时间:2016-03-23 21:25:17

标签: mysql sql

我有3个表,personscompaniestasks

人们在不同的公司做不同的任务。

我想要的是所有人员表的列表,他们在任务中的最后一项任务以及执行该任务时公司的名称。最近的任务可能是最新的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,但结果不合适。

感谢任何帮助。

5 个答案:

答案 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