PostgreSQL:将一行的值添加到另一行,然后删除前者

PostgreSQL:将一行的值添加到另一行,然后删除前者,postgresql,Postgresql,通过一些模糊的错误,可能是在我这一年的变化中,我在我的表中列出了2011-52年的价值,列出了玩家在一周内赢得的虚拟货币,实际上属于2011-01年: # select * from pref_money where id='OK324712148886'; id | money | yw ----------------+-------+--------- OK324712148886 | 203 | 2010-46 OK324712148886 |

通过一些模糊的错误,可能是在我这一年的变化中,我在我的表中列出了2011-52年的价值,列出了玩家在一周内赢得的虚拟货币,实际上属于2011-01年:

# select * from pref_money where id='OK324712148886';
       id       | money |   yw
----------------+-------+---------
 OK324712148886 |   203 | 2010-46
 OK324712148886 |   219 | 2010-49
 OK324712148886 |   115 | 2010-51
 OK324712148886 |    63 | 2011-52
 OK324712148886 |    20 | 2011-01
为了解决这个问题,我想将yw='2011-52'行的值63添加到yw='2011-01'行的值20,然后删除表中每个id的前一行

因此,我尝试使用PostgreSQL 8.4.6/CentOS 5.5:

# update pref_money set money=money+
    (select money from pref_money where yw='2011-52') 
    where yw='2011-01';
ERROR:  more than one row returned by a subquery used as an expression
这可能是因为我也需要在子查询的圆括号内指定id?请问我如何解决我的问题

谢谢大家!!亚历克斯

更新2:

我也试过:

# update pref_money set money=money+
(select money from pref_money m2 where m2.yw='2011-52' and id=m2.id) 
where yw='2011-01';
ERROR:  more than one row returned by a subquery used as an expression

以及:

我的表定义是:

# \d pref_money
                        Table "public.pref_money"
 Column |         Type          |                Modifiers
--------+-----------------------+-----------------------------------------
 id     | character varying(32) |
 money  | integer               | not null
 yw     | character(7)          | default to_char(now(), 'YYYY-IW'::text)
Indexes:
    "pref_money_yw_index" btree (yw)
Foreign-key constraints:
    "pref_money_id_fkey" FOREIGN KEY (id) REFERENCES pref_users(id)
当然,我有数千行不同的id,或者我只需要手工修改1个值,在Stackoverflow上不会问任何问题


我不同意这个评论,2011-52在2011年初可能是一个正确的值。

您需要确保子查询按照错误消息的建议只返回一行。您的示例数据没有显示这一点,但表中显然不止一行有yw='2011-01'

如果id列是主键或主键的一部分,那么将其添加到内部select将纠正此问题

update pref_money set money=money + (select money from pref_money m2 where m2.yw = '2011-52' and m2.id = pref_money.id) where yw='2011-01';
这可能不是一个真正的错误。这201年的第一周在国际标准化组织(ISO)年中实际上是52周。有时是0,有时是52

因此,您可能不想要每周的ISO编号,因为在按订单查询时可能会出现问题。或者尝试将2011-52改为2010-52


不要合并2011-52和2011-01,2011-01从2011年1月3日开始。2011年1月1日和2011年1月2日是第52周

其中一种可能是使用聚合并执行以下操作:

  update pref_money as pm 
     set money = money+money_delta
    from ( select id, sum(money) as money_delta 
             from pref_money as pmt 
            where yw > '2011-01' -- here you should include only the records, that are really corrupted
                                 -- for the example of the data from you, text > should work
            group by id) as pmd
   where pm.id = pmd.id;
     and pm.yw = '2010-01';
但说实话,我会为yw字段使用一个日期数据类型,并设置一个约束date_trunc'month',yw::date=yw,以确保yw中的日期仅为该月的第一天

我最后做了:

# update pref_money as m1 set money=money+
      coalesce((select money from pref_money as m2 
      where m1.id=m2.id and m2.yw='2011-52'),0) 
      where m1.yw='2010-52';
UPDATE 2081

# delete from pref_money where yw='2011-52';
DELETE 1223

我应该首先使用iyy-IW而不是yyy-IW,这两个提示都来自pgsql-general@postgresql.org邮件列表

你是指m2.id=m1.id吗?如果2011-52年度没有钱购买表中的某个用户id,该怎么办?我需要在子查询中添加coalesce吗?我得到错误:更新pref_money m1 set m1.money=m1.money+从pref_money m2中选择money,其中m2.yw='2011-52'和m1.id=m2.id,其中m1.yw='2011-01';错误:关系pref_money的m1列不存在第1行:更新pref_money m1集合m1。money=m1。money+选择money fro…您不能为正在更新的表使用别名。我在我的例子中修复了打印错误,如果是一年的话,请忽略这个月的评论:你好,不幸的是,即使我在中间省略了多余的分号,也不能得到你的解决方案——它告诉我更新是的,我在使用ISO星期号,并且更新了我的问题来显示这个。但你确定2011年初会有一周的52号吗?我重新启动了我的脚本,现在使用了2011-01的yw,可能我以前使用了非ISO周数,忘记了更新生产脚本,所以我需要合并我的值。我确定52可以存在一个开始周,我面前有我的2011日历,前两天在52周,今天是1,今年没有0人:-。阅读维基百科链接,我没有撒谎。是的,2011-01-01和2011-01-02在第52周,但它们在2010年第52周,所以正确的规格应该是2010-52。好的,那么我需要将这两天添加到2010-52,并出于任何原因将2011-52放在当前的位置。因此,我仍然需要一个关于不使用SQL UPDATE命令的原始问题的答案……也许您可以编写一个简单的PHP脚本,使用一些foreach循环,以“保持愚蠢简单”的方式完成所有需要的查询,一次完成,然后删除文件,避免使用复杂的SQL UPDATE查询破坏数据?
  update pref_money as pm 
     set money = money+money_delta
    from ( select id, sum(money) as money_delta 
             from pref_money as pmt 
            where yw > '2011-01' -- here you should include only the records, that are really corrupted
                                 -- for the example of the data from you, text > should work
            group by id) as pmd
   where pm.id = pmd.id;
     and pm.yw = '2010-01';
# update pref_money as m1 set money=money+
      coalesce((select money from pref_money as m2 
      where m1.id=m2.id and m2.yw='2011-52'),0) 
      where m1.yw='2010-52';
UPDATE 2081

# delete from pref_money where yw='2011-52';
DELETE 1223