【问题标题】:UPDATE table in postgreSQLpostgreSQL 中的 UPDATE 表
【发布时间】:2020-08-30 19:18:48
【问题描述】:

my quest for db clean-up 之后,我遇到了一个新问题。对于某些最新价值(此处为“2020-08-04”),我在同一份合同上有两条记录。这是它目前的样子:

asofdate        contract                id   
"2020-08-04"    "AAPL200807C00180000"   7632063
"2020-08-04"    "AAPL200807C00180000"   7740504

还有一些其他的专栏,但我觉得不重要。我的目标是更新表(public."OptionsData"),以便对于 asofdate = '2020-08-04' 的每个重复合同,较小的 id 保持不变,而具有较大 id 的记录的 asofdate 更新为 ' 2020-08-05'

因此从我之前的表格来看,更新后的版本是

asofdate        contract                id   
"2020-08-04"    "AAPL200807C00180000"   7632063
"2020-08-05"    "AAPL200807C00180000"   7740504

我从上一个答案中尝试了以下(改编的)代码:

UPDATE public."OptionsData" d1
SET d1.asofdate = '2020-08-05'
WHERE d1.asofdate = '2020-08-04'
AND EXISTS (SELECT *
              FROM public."OptionsData" d2
              WHERE d1.id > d2.id
              AND (d1.asofdate, d1.contract) 
                = (d2.asofdate, d2.contract)
           )

我也在第一行尝试了 AS d1,但同样的问题:

ERROR:  column "d1" of relation "OptionsData" does not exist

我应该只使用 d2 别名并删除对 d1 的引用吗?

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    您的查询几乎正确。 Postgres 不允许在 SET field = some_expressiion 行的左侧使用表别名 (d1):


    UPDATE public."OptionsData" d1
    SET asofdate = '2020-08-05' -- <<-- Here
    WHERE d1.asofdate = '2020-08-04'
    AND EXISTS (SELECT *
                  FROM public."OptionsData" d2
                  WHERE d1.id > d2.id
                  AND (d1.asofdate, d1.contract) 
                    = (d2.asofdate, d2.contract)
               );
    

    【讨论】:

      【解决方案2】:

      假设 id 是唯一的,您可以使用 row_number() 枚举每天的行。然后在row_number()大于1时增加日期:

      update OptionsData od
          set asofdate = od.asofdate + (seqnum - 1) * interval '1 day'
          from (select od2.*,
                       row_number() over (partition by asofdate, contract order by id) as seqnum
                from OptionsData od2
               ) od2
          where od2.id = od.id and od2.seqnum > 1;
      

      如果您想将此限制在特定日期,请使用where 子句:

      update OptionsData od
          set asofdate = od.asofdate + (seqnum - 1) * interval '1 day'
          from (select od2.*,
                       row_number() over (partition by asofdate, contract order by id) as seqnum
                from OptionsData od2
                where asofdate = '2020-08-04'
               ) od2
          where od2.id = od.id and od2.seqnum > 1;
      

      【讨论】:

        猜你喜欢
        • 2021-12-17
        • 2021-02-11
        • 2012-05-01
        • 2021-04-24
        • 1970-01-01
        • 2019-09-04
        • 1970-01-01
        • 2019-02-23
        • 2020-03-21
        相关资源
        最近更新 更多