如何从mysql中的另一个表获取多个行/列匹配

时间:2019-01-11 23:46:49

标签: mysql join subquery

我有一个记录表和一个历史记录表,它们在记录流过我们的系统时添加时间戳。他们看起来像这样...

records
+------+-----------+----+
|   id | name      | ...|
+------+-----------+----+
|    1 | host1     | ...|
|    2 | host2     | ...|
|    3 | host3     | ...|
|    4 | host4     | ...|
+------+-----------+----+

history
+----+-----------+------------+--------+--------+
| id | record_id | timestamp  | module | status |
+----+-----------+------------+--------+--------+
|  5 | 1         | 2019-01-01 | eng    | new    |
|  6 | 1         | 2019-01-03 | eng    | done   |
|  7 | 2         | 2019-01-01 | eng    | new    |
|  8 | 2         | 2019-01-04 | eng    | done   |
|  9 | 3         | 2019-01-02 | eng    | new    |
+----+-----------+------------+--------+--------+

由于记录表可能包含或可能不包含许多不同的模块和状态条目,因此大大简化了此过程,具体取决于记录工作流程。我需要的是一个记录列表,以及NEW和DONE的时间戳(如果它们存在的话)或null(如果不存在的话),像这样...

+------+-----------+----------------+---------------+
|   id | name      | eng_start_time |  eng_end_time |
+------+-----------+----------------+---------------+
|    1 | host1     | 2019-01-01     | 2019-01-03    |
|    2 | host2     | 2019-01-01     | 2019-01-04    |
|    3 | host3     | 2019-01-02     | null          |
|    4 | host4     | null           | null          |
+------+-----------+----------------+---------------+

我能够通过使用2个子查询来获得这些结果,但是我担心由于这些表变得非常大,这样做可能没有效率。这是我的查询有效。有没有一种方法可以通过更有效的联接/子选择来获得这些结果?

select r.id, r.name, 
  (select timestamp from history where request_id = r.id and module="eng" and status="new") as eng_start_time,
  (select timestamp from history where request_id = r.id and module="eng" and status="done") as eng_end_time
  from records r order by r.id

2 个答案:

答案 0 :(得分:1)

您似乎需要一些LEFT JOIN:

select r.id, r.name, hs.timestamp as eng_start_time, he.timestamp as eng_end_time
  from records r
  left join history hs on r.id = hs.request_id and hs.module="eng" and hs.status="new"
  left join history he on r.id = he.request_id and he.module="eng" and he.status="done"
  order by r.id

答案 1 :(得分:1)

您可以通过左两个JOIN来实现。

select r.id, r.name, h_start.timestamp eng_start_time, h_end.timestamp eng_end_time
from records r
left join history h_start 
    ON h_start.request_id = r.id AND h_start.module='eng' AND h_start.status='new'
left join history h_end
    ON h_end.request_id = r.id AND h_end.module='eng' AND h_end.status='done'
order by r.id

注意:我用双引号替换了双引号,这是SQL中的一种更好的做法。