连接这两个表的方法是什么?

时间:2019-11-19 22:33:26

标签: mysql sql database

说我有2个表A和B,分别包含开始时间和结束时间的信息。主键是id和时间戳的组合。因此,没有2条记录可以具有相同的ID和时间戳

A

id | start time
1 | 2016-02-06 17:03
1 | 2016-03-09 18:09
2 | 2017-02-07 23:34
3 | 2016-02-07 19:12
3 | 2016-02-07 23:52
...

B

id | end time
1 | 2016-02-06 18:32
1 | 2016-03-09 21:11
2 | 2017-02-08 01:22
3 | 2016-02-07 21:32
3 | 2016-02-08 02:11
...

我的最终结果应该是类似

id | start time | end time
1 | 2016-02-06 17:03 | 2016-02-06 18:32
1 | 2016-03-09 18:09 | 2016-03-09 21:11
2 | 2017-02-07 23:34 | 2017-02-08 01:22
3 | 2016-02-07 19:12 | 2016-02-07 21:32
3 | 2016-02-07 23:52 | 2016-02-08 02:11
...

很显然,我不能只加入ID,因为ID 1和ID 3都出现两次。我也无法参加这一天,因为第三和第五条记录跨越了2天。那么有没有办法联接这两个表?任何帮助将非常感激!谢谢!

3 个答案:

答案 0 :(得分:1)

我同意Barmar,并鼓励您重新访问数据模型。我希望开始时间和结束时间在同一张表中。

尽管现有的ID可能用于user_id之类的东西,但是如果该ID在此表中重复,则应该有一些其他唯一的标识符(例如transaction_id)可以唯一地标识每条记录。

答案 1 :(得分:1)

由于ID相同,并且结束日期高于开始日期。

如果这些时间是字符串,则使用STR_TO_DATE

SELECT a.id, a.`start time`, MIN(b.`end time`) AS `end time`
FROM A a
LEFT JOIN B b 
  ON b.id = a.id
 AND STR_TO_DATE(b.`end time`, '%Y-%m-%d %H:%i') > STR_TO_DATE(a.`start time`, '%Y-%m-%d %H:%i')
GROUP BY a.id, a.`start time`
ORDER BY a.id, a.`start time`;

如果是时间戳记

SELECT a.id, a.`start time`, MIN(b.`end time`) AS `end time`
FROM A a
LEFT JOIN B b
  ON b.id = a.id
 AND b.`end time` > a.`start time`
GROUP BY a.id, a.`start time`
ORDER BY a.id, a.`start time`;

在妊娠here上进行的测试

每个B.id是否有很多时间戳?
如果范围限制为一天或更短,则可能会更有效。

SELECT a.id, a.`start time`, MIN(b.`end time`) AS `end time`
FROM A a
LEFT JOIN B b
  ON b.id = a.id
 AND b.`end time` > a.`start time` 
 AND b.`end time` < TIMESTAMPADD(HOUR,24,a.`start time`)
GROUP BY a.id, a.`start time`
ORDER BY a.id, a.`start time`;

答案 2 :(得分:0)

假设同一id的开始/结束时间之间没有重叠,则可以使用基于相关子查询的连接条件联接表,以确保tableb的记录在选择end_time的当前start_time之后,具有最接近的tablea

select
    a.*,
    b.end_time
from
    tablea a
    inner join tableb b
        on  b.id = a.id
        and b.end_time = (
            select min(b1.end_time)
            from tableb b1 
            where b1.id = a.id and b1.end_time > a.start_time
        )

Demo on DB Fiddle

id | start_time       | end_time        
-: | :--------------- | :---------------
 1 | 2016-02-06 17:03 | 2016-02-06 18:32
 1 | 2016-03-09 18:09 | 2016-03-09 21:11
 2 | 2017-02-07 23:34 | 2017-02-08 01:22
 3 | 2016-02-07 19:12 | 2016-02-07 21:32
 3 | 2016-02-07 23:52 | 2016-02-08 02:11