完全外部自我加入不同日期的数据

Posted

技术标签:

【中文标题】完全外部自我加入不同日期的数据【英文标题】:Full Outer Self join with data for different date 【发布时间】:2020-06-22 21:58:12 【问题描述】:

我想将值与第二天的值进行比较(并且还想查看哪种颜色是新的或未出现的)。

我已经完成了完整的外部自连接并替换了“is_matched”右侧部分中的空值。 Is_matched 向我们展示了加入是否有效,或者右侧的部分在没有合并的情况下将为空。

唯一的事情是最后一列“this_is_not_working”。它应该有'date_local2'的total_colours值,而不是'date_local',我不知道如何用'this_is_not_working'列中的值替换所有空值。我尝试过使用窗口函数和间隔,但并没有真正奏效。

我使用 Postgres 创建了这个 db fiddle,但我使用的是 Presto。

select * from colours
日期本地 |颜色 |数量 :--------- | :----- | -----: 2020-01-01 |白色 | 10 2020-01-01 |白色 | 10 2020-01-01 |绿色 | 20 2020-01-01 |白色 | 10 2020-01-01 |红色 | 25 2020-01-01 |白色 | 10 2020-01-02 |粉红色 | 15 2020-01-02 |粉红色 | 15 2020-01-02 |粉红色 | 15 2020-01-02 |粉红色 | 15 2020-01-02 |白色 | 10 2020-01-02 |白色 | 10 2020-01-02 |白色 | 10 2020-01-02 |白色 | 10 2020-01-02 |白色 | 10 2020-01-03 |粉红色 | 15 2020-01-03 |粉红色 | 15 2020-01-03 |粉红色 | 15 2020-01-03 |绿色 | 20 2020-01-03 |绿色 | 20 2020-01-03 |绿色 | 20
with a as( 
    select
        *
        ,sum(colours) over(partition by date_local) as total_colour
    from ( 
        select 
            date_local
            ,colour
            ,count(colour) as colours 
            ,sum(amount) as amount 
        from colours
        group by 1,2
    ) as fr_om 
) 

select
    a.*
    ,b.date_local as is_matched
    ,coalesce(b.date_local, a.date_local + interval '1' day) as date_local_2
    ,coalesce(b.colour, a.colour) as colour_2
    ,coalesce(b.colours, 0) as colour_2
    ,coalesce(b.amount, 0) as amount_2
    ,coalesce(b.colours - a.colours, a.colours) as colour_difference
    ,coalesce(b.amount - a.amount, a.amount) as amount_difference
    ,b.total_colour as this_is_not_working
from a 
full outer join a as b 
    on a.date_local = b.date_local - interval '1' day 
    and a.colour = b.colour
order by 1
日期本地 |颜色 |颜色 |金额 |总颜色 | is_matched | date_local_2 |颜色_2 |颜色_2 |金额_2 |颜色差异 |金额差异 | this_is_not_working :--------- | :----- | ------: | -----: | ------------: | :--------- | :----------------- | :------- | --------: | --------: | ----------------: | ----------------: | ------------------: 2020-01-01 |红色 | 1 | 25 | 6 | | 2020-01-02 00:00:00 |红色 | 0 | 0 | 1 | 25 | 2020-01-01 |绿色 | 1 | 20 | 6 | | 2020-01-02 00:00:00 |绿色 | 0 | 0 | 1 | 20 | 2020-01-01 |白色 | 4 | 40 | 6 | 2020-01-02 | 2020-01-02 00:00:00 |白色 | 5 | 50 | 1 | 10 | 9 2020-01-02 |粉红色 | 4 | 60 | 9 | 2020-01-03 | 2020-01-03 00:00:00 |粉红色 | 3 | 45 | -1 | -15 | 6 2020-01-02 |白色 | 5 | 50 | 9 | | 2020-01-03 00:00:00 |白色 | 0 | 0 | 5 | 50 | 2020-01-03 |粉红色 | 3 | 45 | 6 | | 2020-01-04 00:00:00 |粉红色 | 0 | 0 | 3 | 45 | 2020-01-03 |绿色 | 3 | 60 | 6 | | 2020-01-04 00:00:00 |绿色 | 0 | 0 | 3 | 60 | | | | | | 2020-01-02 | 2020-01-02 00:00:00 |粉红色 | 4 | 60 | | | 9 | | | | | 2020-01-01 | 2020-01-01 00:00:00 |白色 | 4 | 40 | | | 6 | | | | | 2020-01-03 | 2020-01-03 00:00:00 |绿色 | 3 | 60 | | | 6 | | | | | 2020-01-01 | 2020-01-01 00:00:00 |绿色 | 1 | 20 | | | 6 | | | | | 2020-01-01 | 2020-01-01 00:00:00 |红色 | 1 | 25 | | | 6

【问题讨论】:

【参考方案1】:

我认为您不需要full join。窗口函数可以完成工作:

select 
    date_local,
    colour,
    no_colour,
    sum_amount,
    total_colour,
    is_matched,
    case when is_matched = 1
        then lead(date_local) over(partition by colour order by date_local)
    end date_local_2,
    case when is_matched = 1
        then lead(colour) over(partition by colour order by date_local) 
    end colour_2,
    case when is_matched = 1 
        then lead(no_colour) over(partition by colour order by date_local) 
    end no_colour_2,
    case when is_matched = 1 
        then lead(sum_amount) over(partition by colour order by date_local) 
    end sum_amount_2,
    case when is_matched = 1 
        then lead(total_colour) over(partition by colour order by date_local) 
    end total_colour_2  
from (
    select
        date_local,
        colour,
        count(*) no_colour,
        sum(amount) sum_amount,
        case when lead(date_local) over(partition by colour order by date_local) 
            = date_local + interval '1' day
            then 1
        end is_matched,
        sum(count(*)) over(partition by date_local) total_colour
    from colours
    group by date_local, colour
) t
order by date_local, colour

内部查询按天和颜色聚合,并计算组级指标以及每天的记录总数;它还设置一个标志,指示第二天是否存在相同颜色的“相邻”记录。

然后,外部查询使用窗口函数lead() 来恢复相邻行的值。

your db fiddle 中,这会产生:

日期本地 |颜色 | no_color |总金额 |总颜色 | is_matched | date_local_2 |颜色_2 | no_colour_2 | sum_amount_2 |总颜色_2 :--------- | :----- | --------: | ---------: | ------------: | ---------: | :----------- | :------- | ----------: | ------------: | -------------: 2020-01-01 |绿色 | 1 | 20 | 6 | | | | | | 2020-01-01 |红色 | 1 | 25 | 6 | | | | | | 2020-01-01 |白色 | 4 | 40 | 6 | 1 | 2020-01-02 |白色 | 5 | 50 | 9 2020-01-02 |粉红色 | 4 | 60 | 9 | 1 | 2020-01-03 |粉红色 | 3 | 45 | 6 2020-01-02 |白色 | 5 | 50 | 9 | | | | | | 2020-01-03 |绿色 | 3 | 60 | 6 | | | | | | 2020-01-03 |粉红色 | 3 | 45 | 6 | | | | | |

【讨论】:

以上是关于完全外部自我加入不同日期的数据的主要内容,如果未能解决你的问题,请参考以下文章

读取并绘制实时实时自我更新 csv 文件

Hive Group by 后自我加入

自我加入在这里没有帮助。我还可以使用啥其他方法?

如何从给定的外部 url 获取数据会话 ID 和所有内容,而不是来自我的应用程序(路由)在 Angular 6

读书笔记|《程序员的自我修养》- 03 静态链接

读书笔记|《程序员的自我修养》- 03 静态链接