如何将 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
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