根据同一行中的行值逐行更新列值

Posted

技术标签:

【中文标题】根据同一行中的行值逐行更新列值【英文标题】:Update column value based on row value in the same row, row by row 【发布时间】:2020-04-13 09:57:16 【问题描述】:

我有一张带有memberIDDate 的表,如下所示:

MEM_ID          DATE        ttl_sales
-------------------------------------
19960124000007  2020-01-19  NULL
19960131001079  2020-01-20  NULL
19960203001249  2020-01-07  NULL
19960205000213  2020-01-14  NULL

我需要从sales_table 更新ttl_sales,条件是使用同一行中的MEM_ID 以及同一行中DATE 之前发生的事务。

我以后可能需要使用类似的功能,但条件更复杂(在给DATE之前加上在某些商店交易,某些产品等),因此欢迎使用相关关键字和解决方案。

我正在使用 SQL Server。

谢谢。

【问题讨论】:

要求您提供预期的输出,如果您到目前为止已经尝试了预期输出的说明/逻辑,该怎么办。 【参考方案1】:

最简单的方法是协调一个子查询,根据成员 mem_id 对 sales 中的行求和:

UPDATE members
SET ttl_sales = (
  SELECT sum(s.amount) 
  FROM sales s 
  WHERE s.sale_date < members.[date] and s.mem_id = members.mem_id
)

我假设 ttl_sales 是总销售额。如果是计数,请使用COUNT(*) 而不是SUM(amount)

您可以在 WHERE 中添加更多子句来满足您对产品、商店等的要求

【讨论】:

【参考方案2】:

在 SQL Server 中,您可以使用可更新的 CTE 和窗口函数。例如,如果你想要累计数,你可以使用row_number()

with toupdate as (
      select t.*,
             row_number() over (partition by memberId order by date) as seqnum
      from t
     )
update toupdate
     set ttl_sales = seqnum;

窗口函数非常灵活,所以它们可能可以做你想做的事情。

【讨论】:

【参考方案3】:

您还可以使用包含INNER JOINSUM 聚合子查询的公用表表达式:

WITH s AS
(
 SELECT s.Mem_ID AS Mem_ID_s, 
        SUM( COALESCE(s.ttl_sales,0) ) AS ttl_sales_s
   FROM sales s
   JOIN members m 
     ON m.Mem_ID = s.Mem_ID
  WHERE s.Date < m.Date
  GROUP BY s.Mem_ID
)
UPDATE m
   SET m.ttl_sales = s.ttl_sales_s
  FROM members as m
  INNER JOIN s 
     ON m.Mem_ID = s.Mem_ID_s;

另请注意,对于NULL 列的NULL 值的情况,使用COALESCE() 函数很重要。

Demo

【讨论】:

考虑在 SUM 中保留 NULL 可能需要了解 -1 + 1(no records) 之间的区别 好吧,好吧,这也可能是另一个选择@CaiusJard

以上是关于根据同一行中的行值逐行更新列值的主要内容,如果未能解决你的问题,请参考以下文章

Rails 3.x 如何根据行值编写全部更新?

从Array1中的特定行值中减去Array2中的行值

使用 T-SQL 根据先前行的值逐行更新表

如何根据字典中的键值逐行向熊猫数据框添加值?

Mysql根据不同的行更新表中的行值

基于不同表的行值对表中的列值求和