我有一个记录表和一个历史表,当记录流经我们的系统时,它会添加时间戳。它们看起来像这样...
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
最佳答案
您可以通过两个左 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 中更好的做法。
关于mysql - 如何从mysql中的另一个表中获取匹配的多行/列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54155491/