5

试图做一个 upsert 来维护用户第一个最后登录的时间戳和平台。但是新引入的 upsert(冲突时插入)不允许插入选择查询的输出。尝试使用 With 但没有用。新的插入是否支持插入查询的输出并在主键冲突的情况下更新现有字段。以下是使用的查询:

INSERT INTO user_first_last (UserId, FirstLoginDate, LastLoginDate,FirstLoginAmt,LastLoginAmt)
select id, fdd,  ldd,  fda,  lda from daily_activity as dp
ON CONFLICT (UserId)
DO UPDATE 
SET         FirstLoginAmt = case when dp.fdd < FirstLoginDate then dp.fda else FirstLoginAmt END,
            LastLoginAmt = case when dp.ldd > LastLoginDate then dp.lda else LastLoginAmt END,
        FirstLoginDate = case when dp.fdd < FirstLoginDate then dp.fdd else FirstLoginDate END,
            LastLoginDate = case when dp.ldd > LastLoginDate then dp.ldd else LastLoginDate END;

它抛出错误:

missing FROM-clause entry for table "dp"
ERROR:  missing FROM-clause entry for table "dp"
LINE 8: SET         FirstLoginAmt = case when dp.fdd < FirstLoginDate ...

使用排除再次给出错误:

INSERT INTO user_first_last (UserId, FirstLoginDate,LastLoginDate,FirstLoginAmt,LastLoginAmt) 
select id, fdd,  ldd,fda,  lda 
from daily_activity 
ON CONFLICT (UserId) 
DO UPDATE  
  SET FirstLoginAmt = case when excluded.fdd < FirstLoginDate then excluded.fda else FirstLoginAmt END, 
      LastLoginAmt = case when excluded.ldd > LastLoginDate then excluded.lda else LastLoginAmt END,FirstLoginDate = case when excluded.fdd < FirstLoginDate then excluded.fdd else FirstLoginDate END,
      LastLoginDate = case when excluded.ldd > LastLoginDate then excluded.ldd else LastLoginDate END;

错误:错误:列excluded.fdd 不存在

我尝试了以下方法,请在您的最后使用复制,这仍然给出错误:

drop table daily_deposits;
create table daily_deposits
(   id int,
    fdd timestamp,
    ldd timestamp,
    fda double precision,
    lda double precision
);

insert into daily_deposits (id, fdd,  ldd,  fda, lda) values (1,'2015-12-01 08:10:50','2015-12-01 10:10:50', 10, 9);
insert into daily_deposits (id, fdd,  ldd,  fda, lda) values (1,'2015-12-02 10:10:50','2015-12-02 12:10:50', 10, 9);
insert into daily_deposits (id, fdd,  ldd,  fda, lda) values (1,'2015-12-04 04:10:50','2015-12-04 08:10:50', 15, 20);

insert into daily_deposits (id, fdd,  ldd,  fda, lda) values (2,'2015-12-01 08:10:50','2015-12-01 10:10:50', 5, 10);
insert into daily_deposits (id, fdd,  ldd,  fda, lda) values (2,'2015-12-02 10:10:50','2015-12-02 12:10:50', 6, 12);
insert into daily_deposits (id, fdd,  ldd,  fda, lda) values (2,'2015-12-03 04:10:50','2015-12-04 08:10:50', 9, 11);

commit;

select * from daily_deposits;

drop table user_first_last;
create table user_first_last
(   UserId int, 
    FirstLoginDate timestamp,
    LastLoginDate timestamp,
    FirstLoginAmt double precision,
    LastLoginAmt double precision
);


INSERT INTO user_first_last AS ufl (UserId, FirstLoginDate,LastLoginDate,FirstLoginAmt,LastLoginAmt) 
select id, fdd,  ldd,fda,  lda 
from daily_deposits 
ON CONFLICT (UserId) 
DO UPDATE  
  SET FirstLoginAmt = case when excluded.fdd < ufl.FirstLoginDate then excluded.fda else ufl.FirstLoginAmt END, 
      LastLoginAmt = case when excluded.ldd > ufl.LastLoginDate then excluded.lda else ufl.LastLoginAmt END,
      FirstLoginDate = case when excluded.fdd < ufl.FirstLoginDate then excluded.fdd else ufl.FirstLoginDate END,
      LastLoginDate = case when excluded.ldd > ufl.LastLoginDate then excluded.ldd else ufl.LastLoginDate END;

ERROR:  column excluded.fdd does not exist
LINE 6:   SET FirstLoginAmt = case when excluded.fdd < ufl.FirstLogi...
                                        ^
********** Error **********

ERROR: column excluded.fdd does not exist
SQL state: 42703
Character: 222
4

2 回答 2

6

根据文档

ON CONFLICT DO UPDATE 中的 SET 和 WHERE 子句可以使用表的名称(或别名)访问现有行,并使用特殊的排除表访问建议插入的行。

特殊记录exluded与表的类型相同user_first_last

insert into user_first_last as u
    (userid, firstlogindate,lastlogindate,firstloginamt,lastloginamt) 
    select id, fdd, ldd, fda, lda 
    from daily_activity 
on conflict (userid) 
    do update set
    firstloginamt = case 
        when excluded.firstlogindate < u.firstlogindate 
        then excluded.firstloginamt 
        else u.firstloginamt 
    end, 
    lastloginamt = case 
        when excluded.lastlogindate > u.lastlogindate 
        then excluded.lastloginamt 
        else u.lastloginamt 
    end,
    firstlogindate = case 
        when excluded.firstlogindate < u.firstlogindate 
        then excluded.firstlogindate 
        else u.firstlogindate 
    end,
    lastlogindate = case 
        when excluded.lastlogindate > u.lastlogindate 
        then excluded.lastlogindate 
        else u.lastlogindate 
    end;
于 2015-12-08T21:11:21.217 回答
4

我也遇到了这个问题,并想在其他正确答案中添加一个澄清信息。

“排除”是指您尝试插入但被拒绝的行。

不同之处在于,在此示例中,您需要引用 exclude.firstlogindate 而不是 exclude.fdd,因为 firstlogindate 是插入时列的名称。

于 2017-07-26T16:47:06.773 回答