在postgres中使用相同的表数据更新表中的多个列?

时间:2015-11-18 12:00:14

标签: sql postgresql sql-update

我正在尝试更新一个包含两列的表格,首先是 marketplace_fee ,其他的是s ettlment_value

更新 marketplace_fee ,需要计算一些列和

计算 settlment_value 需要marketplace_fee。

问题是:

第一次运行更新查询时,它只更新marketplace_fee而不是Settlment_value,但是当再次执行时,它会更新两列。

查询

update 
    fk_pay_cal 
set 
    marketplace_fee = (((((totalprice * commission  )/100) + shippingcharge + fixed_fee))+
            ((((totalprice * commission  )/100) + shippingcharge +
            fixed_fee)) * (service_tax) /100) ,
    settlment_value = totalprice - marketplace_fee

4 个答案:

答案 0 :(得分:3)

您的括号表达式可以用更简单的形式写下来。在两个作业中使用它两次:

update 
    fk_pay_cal 
set 
    marketplace_fee = 
        (totalprice * commission/100 + shippingcharge + fixed_fee) * (service_tax /100+ 1),
    settlment_value = 
        totalprice 
        - (totalprice * commission/100 + shippingcharge + fixed_fee) * (service_tax /100+ 1);

答案 1 :(得分:1)

一种方法是在CTE中进行计算。如果您在数据上有唯一的ID或主键,这将非常有用:

with newvals as (
      select pc.*,
             (((((totalprice * commission  )/100) + shippingcharge + fixed_fee))+
            ((((totalprice * commission  )/100) + shippingcharge +
            fixed_fee)) * (service_tax) /100) as new_markeplace_fee
      from fk_pay_cal
     )
update fk_pay_cal
    set market_place_fee = new_markeplace_fee,
        settlment_value = totalprice - new_marketplace_fee
    from newvals
    where newvals.id = fk_pay_cal.id;

答案 2 :(得分:1)

此行为是有意的。对作业的右侧侧的列的任何引用都使用" old"该列的值。否则你就不能做update foo set x=y, y=x;

之类的事情

我猜你不想重复这个公式,你需要使用两步法在一个查询中更新它:

with calculated as (
  select pk_column, 
         (((((totalprice * commission  )/100) + shippingcharge + fixed_fee))+
            ((((totalprice * commission  )/100) + shippingcharge +
            fixed_fee)) * (service_tax) /100) as marketing_fee
  from fk_pay_cal 
  where pk_column = ... --<< make sure you only select those that you want to change
) 
update fk_pay_cal 
  set marketplace_fee = c.marketplace_fee,
     settlment_value = totalprice - c.marketplace_fee
from calculated c 
where c.pk_column = fk_pay_cal.pk_column;

您需要将pk_column替换为表格主键列的真实姓名。

编辑如果您没有主键(为什么?),请将pk_column替换为ctidwhere是可用于某个行的内部标识符像这样的情况(但 适合作为主键的一般替代品)

如果您打算更新表格中的所有行,那么您当然需要删除CTE中的create or replace function calc_fee(p_pay fk_pay_cal) returns numeric as $$ select (((((p_pay.totalprice * p_pay.commission) / 100) + p_pay.shippingcharge + p_pay.fixed_fee)) + ((((p_pay.totalprice * p_pay.commission )/100) + p_pay.shippingcharge + p_pay.fixed_fee)) * (p_pay.service_tax) /100); $$ language sql stable; 子句。

另一个选项(从长远来看可能更好)是创建一个封装此公式的函数:

update fk_pay_cal 
  set marketplace_fee  = calc_fee(fk_pay_cal), 
      settlment_value = totalprice - calc_fee(fk_pay_cal);

然后你可以在update语句中使用该函数:

stable

声明函数{{1}} Postgres每行只调用一次。

答案 3 :(得分:1)

我假设ID是PK列

   with cte (
          update 
    fk_pay_cal 
set 
    marketplace_fee = (((((totalprice * commission  )/100) + shippingcharge + fixed_fee))+
            ((((totalprice * commission  )/100) + shippingcharge +
            fixed_fee)) * (service_tax) /100) 
    returning marketplace_fee,id)
    )
   update 
    fk_pay_cal set settlment_value = cte.marketplace_fee  from cte where cte.id=fk_pay_cal.id

或使用ctid

 with cte (
          update 
    fk_pay_cal 
set 
    marketplace_fee = (((((totalprice * commission  )/100) + shippingcharge + fixed_fee))+
            ((((totalprice * commission  )/100) + shippingcharge +
            fixed_fee)) * (service_tax) /100) 
    returning marketplace_fee,ctid)
    )
   update 
    fk_pay_cal set settlment_value = cte.marketplace_fee  from cte where cte.ctid=fk_pay_cal.ctid