如何将 Table A 中的日期与 Table B 中的日期范围相匹配,并从 Table B 中获取相应的数据

How to match dates from Table A with a date range in Table B and bring corresponding data from Table B

Table一个

**ID      empID       log_date_time**
1        1234        2019-10-06 01:00  
2        1234        2019-10-07 03:00

Table B

**empID          start_date_time     end_date_time**
1234           2019-10-06 22:00    2019-10-07 02:00

预期输出

Table C

**ID      empID       log_date_time         within_range_flag**
1        1234        2019-10-06 01:00            1
2        1234        2019-10-07 03:00            0

Table A 中有大约 10,000,000 条记录,Table B 中有 15,000 条记录。 我试过加入,但似乎要花很长时间才能处理。

知道如何将 Table A 日期时间与 Table B 的日期时间范围相匹配吗?

谢谢。

---编辑 我还需要带入 Table B 的信息以供参考。所以预期的输出是

Table C

**ID      empID       log_date_time         within_range_flag         start_date_time     end_date_time**
1        1234        2019-10-06 01:00            1                  2019-10-06 22:00    2019-10-07 02:00
2        1234        2019-10-07 03:00            0                  2019-10-06 22:00    2019-10-07 02:00

规范的解决方案是:

select a.*,
       (case when exists (select 1
                          from tableB b
                          where b.empId = a.empId and
                                a.log_date_time between b.start_date_time and b.end_date_time
                         )
             then 1 else 0
        end) as in_range
from tableA a;

对于此查询,我建议在 tableB(empId, start_date_time, end_date_time) 上建立索引。

试试这个:

select a.ID,
       a.empID,
       a.log_date_time,
       x.within_range_flag,
       x.start_date_time,
       x.end_date_time
from Table_A a
     outer apply (
       select b.start_date_time,
              b.end_date_time,
              case when a.log_date_time between b.start_date_time and b.end_date_time
                   then 1 else 0 end as within_range_flag
       from Table_b b
       where a.empID = b.empID
      ) x

有正确答案:

   select a.ID,
          a.empID,
          a.log_date_time,
          case 
          when a.log_date_time between B.start_date_time and b.end_date_time then 1 
          else 0 
          end as within_range_flag,
          b.start_date_time,
          b.end_date_time
   from Table_A a
   left join Table_B b on b.empID = a.empID

试试这个:

select
    ID, empID, log_date_time,
    case when start_date_time is null then 0 else 1 end within_range_flag, start_date_time
from (
  select a.ID, a.empID, log_date_time, min(start_date_time) start_date_time
  from tableA a
  left join tableB b on b.empID = a.empID
    and a.log_date_time between b.start_date_time and b.end_date_time
  group by a.ID, a.empID, log_date_time
) x

这是通过使用聚合将所有连接表 B 的行折叠为一个值来获得最早的 start_date_time 来实现的。如果没有任何连接行,start_date_time 将是 null,您可以使用该事实生成标志值。

这假定您想要表 B 中所有匹配行中最早的 start_date_time。如果您想要最新的,请使用 max()。如果您想要不同的东西,请不要使用此查询。

您应该在 tableB(empId, start_date_time, end_date_time) 上创建索引。


tableB 中最多有 1 行连接的情况下,可以通过消除内部查询来简化查询(并且可能会执行得更快):

select
    a.ID, a.empID, log_date_time,
    case when start_date_time is null then 0 else 1 end within_range_flag,
    start_date_time
from tableA a
left join tableB b on b.empID = a.empID
    and a.log_date_time between b.start_date_time and b.end_date_time