Igo*_*gor 17 sql sql-server sql-server-2012
我正在使用一个包含信用交易的表格,我想要显示销售时花费的信用额度.
在表中:
Credits由实体使用唯一实体代码添加(记录在列中GivenByUserCode)GivenByUserCodeis null).如果用户2018-01-02在报表上进行购买,则使用上述数据作为示例,应显示源自的所有这些信用BM01.增加的复杂性在于购买可以分为多个添加,请参阅购买2018-02-03分为3个添加.
我认为解决方案将与使用cte和over有关,但我没有使用这些的经验.我确实在SqlServerCentral上发现了类似(不相同)的问题.
任何帮助/方向将是最受欢迎的.
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)
Run Code Online (Sandbox Code Playgroud)
以表格形式输入
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
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
产生输出
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
Run Code Online (Sandbox Code Playgroud)
它并不多,我不知道从哪里开始.
WITH totals AS (
SELECT CreditLogId, OccurredOn, credits, sum(credits) OVER(ORDER BY OccurredOn) AS TotalSpent
FROM @CreditLogs
WHERE Credits < 0
)
SELECT *
FROM totals
Run Code Online (Sandbox Code Playgroud)
预期产出是用于这些信用来自的每个用过的信用额度.积分以先进先出(FIFO)为基础.这里解释了样本输出中的每个值,希望这可以澄清所需的输出.
请注意,剩余6个学分的总余额,余额不必为零,但永远不会为负,因为用户只能花费他们所拥有的.
Ada*_*nko 10
试试这个:
WITH Credits_added AS (
SELECT CreditLogId, OccurredOn, credits
, SUM(credits) OVER (ORDER BY CreditLogId) - credits AS b --before
, SUM(credits) OVER (ORDER BY CreditLogId) AS a --after
, GivenByUserCode
FROM @CreditLogs
WHERE Credits > 0)
, Credits_spent AS (
SELECT CreditLogId, OccurredOn, credits
, SUM(credits) OVER (ORDER BY CreditLogId) * -1 + credits AS b
, SUM(credits) OVER (ORDER BY CreditLogId) * -1 AS a
FROM @CreditLogs
WHERE Credits < 0)
SELECT s.CreditLogId, s.OccurredOn
, CASE WHEN a.a > s.a THEN s.a ELSE a.a END - CASE WHEN a.b > s.b THEN a.b ELSE s.b END AS Credits
, a.GivenByUserCode
FROM Credits_added AS a
INNER JOIN Credits_spent AS s ON a.a > s.b AND s.a > a.b
Run Code Online (Sandbox Code Playgroud)
既然你提到每年会有400到500万条记录,即使这可以通过查询来完成,也会是一个缓慢的查询.
我建议有另一个creditSpent包含的表(PurchaseCreditLogId , additionCreditLogId, Amount)
在插入购买时,查找所有记录,计算应从每个记录中减少的金额,并将该信息存储在该表中
然后,当您运行报表时,可以对此表执行简单查询
| 归档时间: |
|
| 查看次数: |
422 次 |
| 最近记录: |