sql - 是否可以在不循环的情况下根据另一个表减去多行?

标签 sql sql-server

假设我有这张表 Rewards

CustomerID DateReceived Point
         1   2020-01-01    15
         1   2020-01-02    20
         2   2020-01-08    20
         2   2020-01-10    10
         3   2020-01-10    50

然后我有这张表 MaxRewards

CustomerID MaxPoint
         1       20
         2       10
         3       30

因此,想法是客户的 Point 组合(求和)永远不应超过 MaxRewards 表中的 MaxPoint,如果超过,那么它将从最近的日期开始减去,所以在上面的例子中,预期的结果应该是

CustomerID DateReceived Point
         1   2020-01-01    15
         1   2020-01-02     5
         2   2020-01-08    10
         2   2020-01-10     0
         3   2020-01-10    30

如何在没有循环的情况下执行查询来更新表?我一直在考虑使用 CROSS APPLY,但我似乎做不好。

最佳答案

以下方法似乎有效:

WITH cte AS (
    SELECT
        r.CustomerID,
        r.DateReceived,
        r.Point,
        mr.MaxPoint,
        COALESCE(SUM(r.Point) OVER (PARTITION BY r.CustomerID ORDER BY r.DateReceived
                                    ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING), 0) AS cumPoints
    FROM Rewards r
    INNER JOIN MaxRewards mr ON r.CustomerID = mr.CustomerID
)

SELECT
    CustomerID,
    DateReceived,
    CASE WHEN cumPoints + Point < MaxPoint
         THEN Point
         ELSE CASE WHEN MaxPoint - cumPoints > 0
                   THEN MaxPoint - cumPoints ELSE 0 END END AS Point
FROM cte
ORDER BY
    CustomerID,
    DateReceived;

screen capture from demo link below

Demo

此处使用的逻辑是在 CTE 中计算日期序列中当前记录之前每个客户的积分总和。然后,我们将两件事之一报告为输出中的 Point。对于累计总和已经大于最大点数的情况,我们报告 0。否则,我们报告最大点数与累计总和之间的差值,它给出了点数来 self 们要添加的当前记录。

关于sql - 是否可以在不循环的情况下根据另一个表减去多行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63543314/

相关文章:

sql - 检测列中导致 SQL 错误的单元格

php - 使用 MySQL 拆分列

sql - 如果出现唯一约束,则在 Sql 中跳过多行插入 Ruby 续集

sql - 使用 sp_help 的表结构

sql-server - SQL 每行连续日期可用

c# - 在 System.Data.SqlDbType 和 Microsoft.SqlServer.Management.Smo.SqlDataType 之间转换

sql-server - WHERE跨越2个表的SQL Server UPDATE

sql - 使用 SQL Loader 和 perl 导入 csv 错误

php - mysql通过外键将主表与另一个表连接

sql - 使用 Sql Server 集成服务连接到 Oracle 数据库