postgresql更新中的运行计数

postgresql更新中的运行计数,postgresql,Postgresql,我正在使用Postgresql,我正在努力更新一个已经创建的列中的一些值,该列的运行计数基于clientID 目标是识别客户何时为“新客户”(之前的值均不包含该customerID),或者客户是否为“现有客户”(在与该客户关联之前至少有一笔交易) 这是我现在得到的图像 这是我想要实现的一个形象 (客户或客户是同一件事) 在我的研究中,我发现使用子查询可能会导致长时间的代码执行,我正在研究如何使用OVER和PARTITION BY子句与CASE混合,但仍然无法找到解决方案(我所有的错误基本上都

我正在使用Postgresql,我正在努力更新一个已经创建的列中的一些值,该列的运行计数基于clientID

目标是识别客户何时为“新客户”(之前的值均不包含该customerID),或者客户是否为“现有客户”(在与该客户关联之前至少有一笔交易)

这是我现在得到的图像

这是我想要实现的一个形象

(客户或客户是同一件事)

在我的研究中,我发现使用子查询可能会导致长时间的代码执行,我正在研究如何使用OVER和PARTITION BY子句与CASE混合,但仍然无法找到解决方案(我所有的错误基本上都是语法错误)

已访问站点,但我仍未能完成任务:


我看了很多类似的问题,但我无法将SELECT查询转换为我需要的UPDATE语句。

通过一些聚合,您可以在不使用OVER/PARTITION(我不知道如何使用)的情况下获得结果

这张表有tid、cid和status列

首先执行一个查询,如果存在具有相同cid和更低tid的行,则为每对选择1;如果不存在这样的行,则选择0

然后应用聚合以获得一行,例如,对于每一对,您知道具有相同cid但tid较低的行数(当然,它可能存在多行)

然后使用CASE-WHEN进行更新,或者进行两次更新,如以下示例所示:

with 
    data as (
        select
            t1.tid, t1.cid, 
            case when t2.tid is null then 0 else 1 end as cnt 
        from tab t1 
        left join tab t2 
            on t1.cid = t2.cid and t1.tid > t2.tid order by t1.tid
), 
    aggreg as (
        select tid, cid, sum(cnt) 
        from data group by tid, cid order by tid
)
update tab set status = 'EXISTING' 
where (tid,cid) in (select tid,cid from aggreg where sum > 0);


当然,您可以考虑用一个简单的更新来运行这两个查询中的第二个查询,其中状态为NULL,应该运行得更快。

< P>您可以使用一个使用运行计数的窗口函数:
select transact_id, client_id, 
       case count(*) over (partition by client_id order by transact_id) 
          when 1 then 'NEW'
          else 'EXISTING'
        end as client_status
from my_table
order by transact_id;
表达式
count(*)over(按客户机id划分,按交易id排序)
统计每个客户机id的行数,直至“当前”行。因此,如果计数为1,则这是客户端id的第一次出现,并显示
NEW
。对于大于1的所有内容,将显示现有的

如果要更新现有列,可以使用上述查询作为更新源

update my_table
  set client_status = t.client_status
from (
  select transact_id, client_id, 
         case  count(client_id) over (partition by client_id order by transact_id) 
            when 1 then 'NEW'
            else 'EXISTING'
          end as client_status
  from my_table
) t
where my_table.transact_id = t.transact_id;
以上假设
transact\u id
是表中的主键或唯一键


首先,感谢您的回复!我试过了,肯定跑得很快。但正如你所说,我不知道如何将它转化为一个陈述式案例。此外,我忘了提到有时customerID缺失,因此案例将有三个选项(新的、现有的和未识别的)。。你说得对。我不认为使用这种方法可以使用CASE/WHEN,我只需要使用2个更新(3个更新处理null cid)样本数据更好地表示为。有关如何创建美观的表格的一些提示,请参见。
update my_table
  set client_status = t.client_status
from (
  select transact_id, client_id, 
         case  count(client_id) over (partition by client_id order by transact_id) 
            when 1 then 'NEW'
            else 'EXISTING'
          end as client_status
  from my_table
) t
where my_table.transact_id = t.transact_id;