有什么方法可以在 Redshift 中根据条件计算 运行 总数?

Is there any way to calculate running total with condition in Redshift?

我是 运行 Redshift 包裹中心的批量可用性模型。在此 table 列中,B 列显示每小时到达的体积。轮班从 1700 开始,到午夜结束。在那段时间里,他们每小时可以处理 50K 个包裹(C 列)。我有前三列的 table,我想知道是否有任何方法可以计算 Redshift 的 D 列?

我想我明白你想要什么,但如果我没有回答你的问题,请提供更多细节。要达到 运行 总数,您需要使用 SUM() window 函数,该函数可以对所有先前行的值求和。

SUM("arrived packages") over ( order by timeinterval rows unbounded preceding )

将为您提供 运行 个“到达的包裹”总数。现在这不是您想要的,但让我们先介绍一下这个重要的功能。

最后一个要求是这变得棘手的地方。您不能为以后“储存”未使用的容量 - 未使用的容量会丢失。因此,可以处理 50,000 个包裹的所有时间都将如此。这将需要分两步完成(查询和子查询)——首先找到 运行 到达的包裹总数和可用吞吐量。然后计算它们之间的差异,但在有未使用容量的任何时候加回去。基本上采用简单的方法并将错误作为最终调整。否则这将成为一个递归问题,而 Redshift 不喜欢这些问题。 (抱歉,下面的 SQL 未经测试,所以以它为名义)

select timeinterval, "arrived packages", "throughput per hour",
    run_tot_pack - run_tot_capacity + 
        sum(decode(run_tot_pack - run_tot_capacity < 0, true, run_tot_capacity - run_tot_pack, 0)) over (order by timeinterval rows unbounded preceding) as "available volume"    
from (
    select timeinterval, "arrived packages", "throughput per hour",
        sum("arrived packages") over (order by timeinterval rows unbounded preceding) as run_tot_pack,
        sum("throughput per hour") over (order by timeinterval rows unbounded preceding) as run_tot_capacity
    from <table>
)
order by timeinterval;

你是对的,我之前的回答漏了一个词。我今天在集群上花了一些时间并编写了一个测试用例。以下是修改后的 SQL 和设置语句。它需要一个新术语,它是一个 window 函数,因为它们不能嵌套另一个 select 层。我希望这个例子能有所帮助,而且我知道解决非递归数据库上的递归问题可能很困难。

drop table if exists package_volume;

create table package_volume (
        A timestamp encode zstd,
        B int encode zstd,
        C int encode zstd);

insert into package_volume values
('2020-06-26 13:00', 0, 0),
('2020-06-26 14:00', 3500, 0),
('2020-06-26 15:00', 3200, 0),
('2020-06-26 16:00', 6500, 0),
('2020-06-26 17:00', 5200, 50000),
('2020-06-26 18:00', 51000, 50000),
('2020-06-26 19:00', 120000, 50000),
('2020-06-26 20:00', 30000, 50000),
('2020-06-26 21:00', 40000, 50000),
('2020-06-26 22:00', 15000, 50000),
('2020-06-26 23:00', 5500, 50000),
('2020-06-27 00:00', 0, 0);

commit;

select A, B, C, 
        run_tot_pack - run_tot_capacity + sum(unrealized_capacity) over (order by A rows unbounded preceding) as available_volume    
from (
    select A, B, C, run_tot_pack, run_tot_capacity, 
        decode(unrealized_capacity - max(unrealized_capacity) over (order by A rows between unbounded preceding and 1 preceding) < 0, true, 0, 
            unrealized_capacity - max(unrealized_capacity) over (order by A rows between unbounded preceding and 1 preceding)) as unrealized_capacity
    from (
                    select A, B, C,
                        sum(B) over (order by A rows unbounded preceding) as run_tot_pack,
                        sum(C) over (order by A rows unbounded preceding) as run_tot_capacity,
                        decode(run_tot_pack - run_tot_capacity < 0, true, run_tot_capacity - run_tot_pack, 0) as unrealized_capacity
            from package_volume
        )
)
order by A;