连接计算日期之间值的表

Posted

技术标签:

【中文标题】连接计算日期之间值的表【英文标题】:Joining tables that compute values between dates 【发布时间】:2018-04-21 16:01:01 【问题描述】:

所以我有以下两个表格

表 A

Date        num
01-16-15    10
02-20-15    12
03-20-15    13

表 B

Date        Value
01-02-15    100
01-03-15    101
   .         .
01-17-15    102
01-18-15    103
   .         .
02-22-15    104
   .         .
03-20-15    110

我想在 impala 中创建一个具有以下输出的表

Date         Value
01-17-15     102*10
01-18-15     103*10
02-22-15     104*12
   .           .
   .           .

所以我们的想法是我们只考虑 01-16-15 和 02-20-15 之间的日期,并且只考虑 02-20-15 和 03-20-15 之间的日期。并使用该期间开始日期的数字,例如 01-16-15,并将其乘以该期间的每天,即 1-16 到 2-20。

我知道应该通过加入来完成,但我不确定在这种情况下你如何加入。 谢谢!

【问题讨论】:

如果您正在考虑该范围内的日期,为什么结果集中没有您正在考虑的所有日期? 因为 1-16 和 2-20 之间的每个日期都将被视为周期 1,而周期 1 将使用 1-16 来确定其中的值,即 1-17 【参考方案1】:

嗯。在标准 SQL 中,您可以这样做:

select b.*,
       (select a.num
        from a
        where a.date <= b.date
        order by a.date desc
        fetch first 1 row only
       ) * value as new_value
from b;

我认为这不符合范围条件,但我不明白你的描述。

我也不知道 Impala 是否支持相关子查询。对于复杂数据,另一种方法可能更快:

with ab as (
      select a.date, a.value as a_value, null as b_value, 'a' as which
      from a
      union all
      select b.date, null as a_value, b_value, 'b' as which
      from b
     )
select date, b_value * a_real_value
from (select ab.*,
             max(a_value) over (partition by a_date) as a_real_value
      from (select ab.*,
                   max(a.date) over (order by date, which) as a_date
            from ab
           ) ab
     ) ab
where which = 'b';

【讨论】:

【参考方案2】:

这适用于 MariaDb (mysql),它非常基础,所以希望它也适用于 impala。

SELECT b.date, b.value * a.num
FROM tableB b, tableA a
WHERE b.date >= a.date
  AND (b.date < (SELECT MIN(c.date) FROM tableA c WHERE c.date > a.date)
       OR NOT EXISTS(SELECT c.date FROM tableA c WHERE c.date > a.date))

最后一个 NOT EXISTS... 需要包含表 A 中最后一个日期之后的日期

更新 在问题的修订版中,B 中的日期永远不会大于(之后)A 中的最后一个日期,因此查询可以写为

SELECT b.date, b.value * a.num
FROM tableB b, tableA a
WHERE b.date >= a.date
  AND b.date <= (SELECT MIN(c.date) FROM tableA c WHERE c.date > a.date)

【讨论】:

你能在这里多解释一下AND的功能吗?而且问题陈述中还有一个错字,我已经修复了它。基本上两张表的最后日期是相同的,这种情况下,不需要NOT EXISTS子句吧? "condition1 AND condition2" 这意味着两个条件都必须为真。所以这里意味着 b.date 需要 >= 来自 A 的日期并且小于表 A 中的下一个日期 所以对于两个表的最后日期相同的修订版,我们只需要 AND (b.date a .date) 对吗? 不,你仍然需要我回答中的完整 WHERE 子句 好的。刚刚在 impala 中尝试过,返回错误:不支持 OR 谓词中的子查询。知道这里发生了什么吗?

以上是关于连接计算日期之间值的表的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 SQL 获取 2 列之间日期差异的计数(值的分布)?

如何用EXCEL计算两个日期之间相差的年数和月数?

计算日期之间的空值

如何计算几个日期之间的记录数

如何计算定义自定义财务日历的两个日期之间的月数?

找到两个日期之间的金额总和