如何在Postgresql中将预算值分配到实际行

如何在Postgresql中将预算值分配到实际行,sql,postgresql,join,aggregate-functions,outer-join,Sql,Postgresql,Join,Aggregate Functions,Outer Join,预算表包含具有以下负载的作业: create temp table budget ( job char(20) primary key, load numeric(4,1) not null check (load>0 ) ); insert into budget values ( 'programmer', 3 ); insert into budget values ( 'analyst', 1.5 ); 实际表包含员工的实际负载: create temp table

预算表包含具有以下负载的作业:

create temp table budget (
  job char(20) primary key,
  load numeric(4,1) not null check (load>0 )
  );
insert into budget values ( 'programmer', 3 );
insert into budget values ( 'analyst', 1.5 );
实际表包含员工的实际负载:

create temp table actual (
  job char(20),
  employee char(20),
  load numeric(4,1) not null check (load>0 ),
  contractdate date,
  primary key (job, employee)
  );

insert into actual values ( 'programmer', 'John',  1, '2014-01-01' );
-- half time programmer:
insert into actual values ( 'programmer', 'Bill', 0.5, '2014-01-02' ); 

insert into actual values ( 'analyst', 'Aldo', 1, '2014-01-03' );
insert into actual values ( 'analyst', 'Margaret', 1, '2014-01-04' ); 
结果表应显示预算作业和实际作业之间的差异,以便减少预算负载 按合同日期顺序分发给员工

如果预算负载大于工作负载之和,则使用空员工分隔预算行 应该出现

在上面的数据中,1.5名程序员失踪,0.5名分析师失踪

结果应该是

Job        Employee  Budget  Actual  Difference

programmer John      1       1       0
programmer Bill      0.5     0.5     0
programmer           1.5     0       1.5
analyst    Aldo      1       1       0
analyst    Margaret  0.5     1       -0.5
如何在现代Postgresql中创建这样的表? 是否可以使用完全联接或其他方法对函数进行排序

我试过了

select
 coalesce(budget.job, actual.job ) as job,
 employee,
 budget.load as budget,
 coalesce(actual.load,0) as actual,
 coalesce(budget.load,0)-coalesce( actual.load,0) as difference
from budget full join actual using (job)
order by 1, contractdate
但这不会将预算负载分配给员工行


我也在pgsql通用邮件列表中发布了此消息。

以下查询得到了您想要的内容:

select job, employee, budget, actual,
       (budget - cumload) as diff, contractdate
from (select coalesce(b.job, a.job ) as job, a.contractdate,
             a.employee,
             b.load as budget,
             coalesce(a.load,0) as actual,
             sum(a.load) over (partition by a.job order by a.contractdate NULLS last) as cumload
      from budget b join
           (select a.*
            from actual a
            union all
            select b.job, NULL, NULL, NULL
            from budget b
           ) a
           on b.job = a.job
     ) ab
where contractdate is not null or budget > cumload
order by job, contractdate
SQL小提琴是

请注意,这将使用
union all
引入查询所需的额外行。您希望通过
完全外部联接
执行此操作,但当满足
联接
条件时,不会生成额外的行


此外,您所寻找的逻辑需要一个累积的总和,Postgres很乐意提供这个总和。

谢谢。在您对作业的回答中,预算列不会更改,因此这是错误的:预算列上的总金额必须等于预算表中的总预算。问题中的期望结果显示作业的已分配预算:如果行中存在“实际”,则预算不得大于“实际”:预算应分配给“实际”,直到它变为0,或者应显示仅包含未填写预算的新行。“差异”列始终是前两列之间的差异。如何解决这个问题?