如何正确连接两个分别具有“开始日期”和“停止日期”列的表?

问题描述 投票:0回答:2

这应该很容易,甚至可能是重复的,但我的大脑和我的搜索引擎今天都没有多大帮助。

我的问题如下:

给定两个表,它们都有:

  1. 开始日期
  2. 停止日期
  3. 员工的财产。假设表 A 中的办公桌号和表 B 中的团队
  4. 员工的唯一ID号。

以某种诚实的方式将两个表连接在一起,这样结果表中的每一行只需要一个开始日期和结束日期。

输入和所需输出示例: 表A:

开始日期 停止日期 身份证 服务台号码
01/20 05/20 0100 55
03/20 06/20 0100 56
02/22 04/22 0200 91

表 B(注意员工 0100 的日期重叠):

开始日期 停止日期 身份证 团队编号
01/20 04/20 0100 2
02/20 06/20 0100 3
02/22 04/22 0200 8

输出示例:

开始日期 停止日期 身份证 服务台号码 团队编号
01/20 04/20 0100 55 2
02/20 05/20 0100 55 3
02/20 06/20 0100 56 3
02/22 04/22 0200 91 8

一旦表正确连接,我就可以处理结果日期,但连接本身给我带来了问题。我只是不知道如何确保某些超出范围的日期不会滑入。我目前的连接解决方案(我不确定)就是加入

[Table A].[Start Date] <= [Table B].[Stop Date]
[Table B].[Start Date] <= [Table A].[Stop Date]

然后适当地取最大/最小日期(不用担心那部分,我只关心连接),但我非常怀疑解决方案真的那么简单。

sql sql-server date t-sql join
2个回答
2
投票

假设我在这里没有出错,所需的输出应该是

开始日期 停止日期 身份证 服务台号码 团队编号
01/20 04/20 0100 55 2
02/20 05/20 0100 55 3
03/20 04/20 0100 56 2
03/20 06/20 0100 56 3
02/22 04/22 0200 91 8

您对连接的直觉确实是正确的,这会产生正确的结果:

SELECT CASE
         WHEN teams.start_date > desks.start_date
         THEN teams.start_date
         ELSE desks.start_date
       END start_date
     , CASE
         WHEN teams.stop_date < desks.stop_date
         THEN teams.stop_date
         ELSE desks.stop_date
       END stop_date
     , desks.id
     , desks.desk_number
     , teams.team_number
  FROM desks
  JOIN teams
    ON desks.start_date < teams.stop_date
   AND teams.start_date < desks.stop_date
   AND teams.id = desks.id

dbfiddle 上的工作演示


0
投票

这应该很容易,甚至可能是重复的,但我的大脑和我的搜索引擎今天都没有多大帮助。

花了两年时间,我的大脑终于开始运转了。 Aaron Bertrand 在这里很好地介绍了这一点。引用他的话

真正重要的是,Event2 在 Event1 开始的同时或之后结束 - 无论它是在早期边界、内部、后期边界还是之后结束,都无关紧要。同样,Event2 需要在 Event1 结束之前或事件 1 结束时开始 - 无论它是在 Event2 之前、在早期边界、内部还是在稍后边界开始都没有关系。

这将逻辑简化为:

WHERE (@E2 >= S1 AND @S2 <= E1)

上面的SQL在逻辑上与原问题中的相同

[Table A].[Start Date] <= [Table B].[Stop Date]
[Table B].[Start Date] <= [Table A].[Stop Date]

但写成

[Table B].[Stop Date] >= [Table A].[Start Date]
[Table B].[Start Date] <= [Table A].[Stop Date]
© www.soinside.com 2019 - 2024. All rights reserved.