我有几种情况需要使用PostgreSQL将整数除以另一个整数并完成三件事:
我现在要处理的具体问题是我每月都有这样的数量:
Month Part Qty
--------- --------- -----
1/1/2016 ABC 10
2/1/2016 ABC 9
就我已经成功而言,这是关于我的前两个目标,但不是我的第三个目标:
with weekly_buckets as (
select generate_series (0, 3) as week_number
)
select
p.month_date + 7 * w.week_number as week_date,
p.part_number,
case w.week_number
when 0 then p.qty / 4
when 1 then p.qty / 4
when 2 then p.qty / 4
when 3 then p.qty - 3 * (p.qty / 4)
end as qty
from
part_demand p
cross join weekly_buckets w
导致:
Week Part Qty
--------- --------- -----
1/1/2016 ABC 2
1/8/2016 ABC 2
1/15/2016 ABC 2
1/22/2016 ABC 4
因此,最后一周的曲棍球棒效果为4。我可以使用天花板而不是地板,但在3,3,3,1时会更糟。
理想情况下,差价看起来像2,3,2,3或3,2,3,2。两者都可以接受。这就是我所说的公平份额差价。如果有一个更加数学上正确的术语,请赐教。
作为参考,这些数量代表月度预测,我们正在尝试确定实际订单是否在预测之前或之后。
此外,如果我能解决这个问题,我可以利用逻辑来做同样的事情来为年度数量创建月度桶。
作为最后一个例子,如果我看到这样的话:
Month Part Qty
--------- --------- -----
1/1/2016 ABC 1
理想情况下,唯一一个非零值的周将是第2周或第3周。它确实无关紧要,但如果您想知道如何处理低值,这就是我所拥有的心。
答案 0 :(得分:1)
您可以使用窗口函数来分配值。这是你的第一个例子:
with b as (
select generate_series(1, 4) as i, 10 as amt
),
bb as (
select b.*,
count(*) over () as numbuckets,
row_number() over (order by i) as rn,
amt % (count(*) over () ) as remainder
from b
)
select bb.*,
(amt / numbuckets +
(case when rn <= remainder then 1 else 0 end)
) as partitioned
from bb;
我们的想法是为每个存储桶分配amt / numbuckets
。然后使用row_number()
将剩余部分分散到存储桶中。如果您希望随机传播值,请使用order by random()
来定义rn
。