【发布时间】:2018-04-24 18:06:26
【问题描述】:
我正在处理一个包含信用交易的表格,我希望在该表格中显示在进行销售时花费了谁的信用。
在表格中:
-
Credits由实体使用唯一的实体代码添加(记录在GivenByUserCode列中) - 信用添加总是有这样的代码。
- 已花费的积分将始终为负值。
- 已花费的积分将没有实体代码(
GivenByUserCode的值为null)。
以上述数据为例,如果用户在2018-01-02 上进行购买,则报告应显示来自BM01 的所有这些积分。增加的复杂性在于,一次购买可以分成多个添加,请参阅2018-02-03 上的购买,它分为 3 个添加。
我认为解决方案与使用 cte 和 over 有关,但我没有使用这些的经验。我确实在SqlServerCentral 上发现了类似(不一样)的问题。
任何帮助/指导将不胜感激。
输入和 DDL
DECLARE @CreditLogs TABLE(CreditLogId int not null identity(1,1), Credits INT NOT NULL, OccurredOn DATETIME2(7) NOT NULL, GivenByUserCode VARCHAR(100) NULL)
INSERT INTO @CreditLogs (Credits, OccurredOn, GivenByUserCode) VALUES
(10, '2018-01-01', 'BM01')
, (10, '2018-01-01', 'BM01')
, (-10, '2018-01-02', NULL)
, (-5, '2018-01-04', NULL)
, (5, '2018-02-01', 'SP99')
, (40, '2018-02-02', 'BM02')
, (-40, '2018-02-03', NULL)
, (-4, '2018-03-05', NULL)
表格输入
CreditLogId | Credits | OccurredOn | GivenByUserCode
------------+---------+------------+----------------
1 | 10 | 2018-01-01 | BM01
2 | 10 | 2018-01-01 | BM01
3 | -10 | 2018-01-02 | NULL
4 | -5 | 2018-01-04 | NULL
5 | 5 | 2018-02-01 | SP99
6 | 40 | 2018-02-02 | BM02
7 | -40 | 2018-02-03 | NULL
8 | -4 | 2018-03-05 | NULL
预期输出
SELECT *
FROM (VALUES
(3, '2018-01-02', 10, 'BM01')
,(4, '2018-01-04', 5, 'BM01')
,(7, '2018-02-03', 5, 'BM01')
,(7, '2018-02-03', 5, 'SP99')
,(7, '2018-02-03', 30, 'BM02')
,(8, '2018-03-05', 4, 'BM02')
) expectedOut (CreditLogId, OccurredOn, Credits, GivenByUserCode)
产生输出
CreditLogId | Occurred on | Credits | GivenByUserCode
------------+-------------+---------+----------------
3 | 2018-01-02 | 10 | BM01
4 | 2018-01-04 | 5 | BM01
7 | 2018-02-03 | 5 | BM01
7 | 2018-02-03 | 5 | SP99
7 | 2018-02-03 | 30 | BM02
8 | 2018-03-05 | 4 | BM02
到目前为止的代码
这并不多,我不知道从这里去哪里。
WITH totals AS (
SELECT CreditLogId, OccurredOn, credits, sum(credits) OVER(ORDER BY OccurredOn) AS TotalSpent
FROM @CreditLogs
WHERE Credits < 0
)
SELECT *
FROM totals
补充说明
预期输出是针对这些信用来源的每个已用信用金额。积分以先进先出 (FIFO) 的方式使用。这里对示例输出中的每个值进行了解释,希望能够阐明所需的输出。
- 对于 10 个信用(信用日志 id 3)的支出可以追溯到信用日志 id 1 的添加
- 对于 5 个信用(信用记录 id 4)的支出,可以追溯到信用记录 2 的添加(因为信用记录 id 1 已“用完”)
- 对于在信用日志 id 7 中花费 40 信用可以追溯到
- 从信用记录 id 2 中添加的剩余部分,5 个信用
- 信用记录ID 5(加5)
- 信用记录 id 6(添加 40 剩余 10)
- 对于信用记录 8 中的 4 个信用的支出,使用信用记录 id 6 的余额
请注意,剩余的总余额为 6 个积分,余额不必归零,但永远不会为负数,因为用户只能花费他们所拥有的。
【问题讨论】:
-
您的预期输出与输入数据不匹配,您能否看看它是否正确或解释您是如何得出输出的?
-
@PankajGadge - 预期输出是针对这些积分来自的每个已用积分金额。积分以先进先出的方式使用。我将更新问题以使其更清楚。
-
@PankajGadge - 请参阅末尾添加的
Additional clarification。如果这仍然引起问题,请告诉我。 -
@scsimon - 我们预计此表中的记录每年将增长 4 到 500 万条(表/历史永远不会被清除)。
-
那么 Adam Silenko 的答案可能是你能得到的最好的答案,因为有一个基于相等性的附加连接条件和每个订单的少量行数。
标签: sql sql-server sql-server-2012