【问题标题】:SQL join only one value when dates overlap日期重叠时 SQL 只连接一个值
【发布时间】:2015-08-17 07:56:30
【问题描述】:

我有 2 张桌子:分配和外籍人士。作业有其 Effective_start_date 和 Effective_end_date。我需要显示有关员工分​​配的信息以及他们前往另一个国家/地区的日期(在分配日期期间)。我有一个 select 语句,稍后会将数据加载到表中。但是该表有一个约束,即 assignment_id、effective_start_date、effective_end_date 的组合必须是唯一的。在外籍人士表上,我没有 assignment_id。因此,我似乎无法正确加入 2 张桌子。我也不能使用 first_value 和 distinct,必须有另一个解决方案。

with assignments (assignment_id, person_id, effective_start_date, effective_end_date) as (
   select 148713, 123, date '2015-03-16', date '4712-12-31' from dual union all
   select 13706, 123, date '2015-03-16', date '4712-12-31' from dual union all
   select 13706, 123, date '2015-01-01', date '2015-03-15' from dual
 ),
 expatriates (person_id, date_from, date_to, home_country, host_country, valid_from, valid_to) as (
   select 123, date '2015-03-16', date '2016-04-15', 'TEST', 'TEST', date '2015-03-16', date'2015-04-15' from dual union all
   select 123, date '2015-01-01', date '2015-03-15', 'TEST2', 'TEST2', date '2015-01-01', date'2015-03-15' from dual union all
   select 123, date '2014-04-16', date '2016-06-15', 'TEST1', 'TEST1', date '2015-04-16', date'2016-06-15' from dual
 ) 

select 
    a.assignment_id, 
    a.person_id, 
    a.effective_start_date,
    a.effective_end_date,
    subq.date_from, 
    subq.date_to, 
    subq.home_country, 
    subq.host_country
from expatriates subq, assignments a
where 
    subq.person_id=a.person_id
and subq.valid_from <= a.effective_end_date
and subq.valid_to >= a.effective_start_date

编辑:忘了提到我不能使用 OR 语句,因为我需要进行的连接实际上是外连接,我不能使用 union all 来解决问题。我只是为了示例使用了内部连接。

编辑编号。 2:还是没有解决办法?

【问题讨论】:

  • 您想要什么结果(对于您的样本数据)?对我来说,您的查询似乎很好。

标签: sql oracle join


【解决方案1】:
select 
    a.assignment_id, 
    a.person_id, 
    a.effective_start_date,
    a.effective_end_date,
    subq.date_from, 
    subq.date_to, 
    subq.home_country, 
    subq.host_country
from expatriates subq, assignments a
where 
    subq.person_id=a.person_id
and (
     (subq.valid_from >= a.effective_start_date and subq.valid_from <= a.effective_end_date)
     or
     (subq.valid_to >= a.effective_start_date and subq.valid_to <= a.effective_end_date)
    )

【讨论】:

  • 这对我不起作用,作业 ID、有效开始日期和有效结束日期组合不是唯一的。而且我一开始没有提到这一点,但我不能使用 or 声明,因为我所做的连接实际上是外连接(我只是为了示例使用了内连接)。而且我不能在外连接中使用 OR 语句。
【解决方案2】:

也许您可以将德摩根定律与 BETWEEN...AND 结合使用来避免 OR?

类似这样:假设您要避免的带有 OR 的子句是这样的:

(
 (subq.valid_from >= a.effective_start_date and subq.valid_from <= a.effective_end_date)
 OR
 (subq.valid_to >= a.effective_start_date and subq.valid_to <= a.effective_end_date)
)

使用 BETWEEN...AND,可以写成:

(
 (subq.valid_from BETWEEN a.effective_start_date AND a.effective_end_date)
 OR
 (subq.valid_to BETWEEN a.effective_start_date AND a.effective_end_date)
)

德摩根定律说NOT A OR NOT B 等价于NOT (A AND B)。所以假设

  1. NOT A(subq.valid_from BETWEEN a.effective_start_date AND a.effective_end_date),并且
  2. NOT B(subq.valid_to BETWEEN a.effective_start_date AND a.effective_end_date)

这样

  1. A(subq.valid_from NOT BETWEEN a.effective_start_date AND a.effective_end_date)
  2. B(subq.valid_to NOT BETWEEN a.effective_start_date AND a.effective_end_date)

(请在 BETWEEN 之前标记 NOT。)

结合德摩根定律,该条款可以不使用 OR:

NOT (
 subq.valid_from 
   NOT BETWEEN a.effective_start_date 
   AND a.effective_end_date 
 AND 
 subq.valid_to 
   NOT BETWEEN a.effective_start_date 
   AND a.effective_end_date
)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-26
    相关资源
    最近更新 更多