所以我在MS SQL Server上有三个表:
类型将付款/储备金分为建筑材料,固定装置,人工成本,专业服务等
因此,当项目开始时,将根据预期成本设置一系列准备金。
您可能最初估计材料的成本为5,000美元,但是在进行了一些查询之后,您意识到材料的成本更像是10,000美元,在这种情况下,设置了10,000美元的新准备金,并且原始项目的表格设置为0
当发票进入并被支付时,它将进入付款表,储备金和付款之间的链接被输入到第三张表中。当在前端向用户显示付款时,将从准备金中扣除付款,但是在后端,未更改准备金表。例如,如果有$ 10,000的物料储备金和$ 2,500的物料发票已支付,则后端仍将有10,000储备金和2.5k付款,但前端将显示7.5k储备金,2.5k付款和共10,000。
如果某笔付款超出某类型的预留金额,那么前端将显示0预留,12,000笔付款和12,000笔总额。 (其他任何类型的储备金都将保持不变-例如,如果材料超出预算5k,则不会减少人工储备。)
如果在付款后更改了储备金(这导致“储备金”表中出现新行),则前端将停止从中扣除先前的付款。因此,在前面的示例中,前端显示7.5k储备金,2.5k付款和10k总数。如果用户然后将储备金更改为10k,则前端将显示10k储备金,2.5k付款和12.5k付款。
做事方式很差,但是我不能改变前端。
所以我需要做的是在任何时间点计算每个项目的最大总计。在理想情况下,这将是当前位置,但是过去可能会高估事物,然后在发现可以修复而不是替换的东西时减少储备。
我完全不知道如何执行此操作,更不用说以有效的方式运行相当大的数据集了。
非常感谢您的帮助。
样本数据
保留
ReserveID ProjectID TypeID DateCreated Current Amount
23 64 4 03/01/2020 0 5,000.00
24 65 3 03/01/2020 1 1,000.00
25 64 4 05/01/2020 1 10,000.00
26 64 1 08/01/2020 1 500.00
27 66 1 09/01/2020 1 750.00
28 64 3 10/01/2020 1 250.00
29 68 3 10/01/2020 0 20,000.00
30 68 3 11/01/2020 1 5,000
付款
PaymentID ProjectID TypeID DateCreated Status Amount
87 64 4 08/01/2020 Declined 10,000.00
88 64 8 09/01/2020 Approved 1,000.00
89 71 2 10/01/2020 Approved 5,000.00
90 66 1 12/01/2020 Approved 700.00
链接
LinksID ReserveID PaymentID
21 25 87
22 25 88
23 27 90
所需的输出
ProjectID MaxPotentialCost
64 11,750.00
65 1,000.00
66 750.00
68 20,000.00
71 5,000.00
答案 0 :(得分:0)
虽然我对您想要的东西还不是很清楚(该示例并不十分稳健或完整)我可以给您一个至少(希望如此)的有效示例涵盖了您似乎想要的方法。
(我将整理自己的数据,以更清楚地说明我的意思...)
3 2 1 110 90
4 3 1 120 90
第一件事似乎是在单个时间序列数据集中而不是在两个时间序列中获得所有数据。然后,到目前为止要有一个连续的付款总数,而不是各个金额。这样一来,每个ProjectID TypeID EffectiveDate Reserve
64 4 01/01/2020 1,000
64 4 07/01/2020 5,000
64 4 11/01/2020 1,000
64 5 12/01/2020 1,000
ProjectID TypeID EffectiveDate Payment
64 4 03/01/2020 1,000
64 4 05/01/2020 1,000
64 4 09/01/2020 2,000
64 5 10/01/2020 3,000
的曝光量(您所指的“总数”)就更容易计算。
(ProjectId,TypeID)
示例SQL:
PID,TID EffectiveDate Reserve Payment NewSpent OldSpent Exposure
64,4 01/01/2020 1,000 0 0 0 1,000 -- Reserve Added
64,4 03/01/2020 1,000 1,000 1,000 0 1,000 -- Payment Made, so newSpent increases
64,4 05/01/2020 1,000 1,000 2,000 0 2,000 -- Payment Made, so newSpent increases
64,4 07/01/2020 5,000 0 0 2,000 7,000 -- Reserve Revised, newSpent is added to OldSpent and then resets to zero
64,4 09/01/2020 5,000 2,000 2,000 2,000 7,000 -- Payment Made, so newSpent increases
64,4 11/01/2020 1,000 0 0 4,000 5,000 -- Reserve Revised, newSpent is added to OldSpent and then resets to zero
64,5 10/01/2020 0 3,000 3,000 0 3,000 -- Payment Made, so newSpent increases
64,5 12/01/2020 1,000 0 0 3,000 4,000 -- Reserve Revised, newSpent is added to OldSpent and then resets to zero
这时,我将其全部折叠到“曝光”已改变的程度,因为这将使交错多个类型变得更加简单。
WITH
combined AS
(
SELECT
payments.ProjectID,
payments.TypeID,
links.ReserveID,
payments.DateCreated,
COALESCE(reserve.Amount, 0) AS reserve,
payments.Amount AS spent
FROM
payments
LEFT JOIN
links
ON payments.PaymentID = links.PaymentID
LEFT JOIN
reserve
ON reserve.ReserveID = links.ReserveID
WHERE
payments.status = 'Approved'
UNION ALL
SELECT
reserve.ProjectID,
reserve.TypeID,
reserve.ReserveID,
reserve.Amount,
0
FROM
reserve
)
,
runningTotal AS
(
SELECT
ProjectID,
TypeID,
DateCreated,
reserve,
SUM(spent)
OVER (PARTITION BY ProjectID, TypeID, ReserveID
ORDER BY DateCreated
)
AS spentReserve,
SUM(spent)
OVER (PARTITION BY ProjectID, TypeID
ORDER BY DateCreated
)
AS spentProjectType
FROM
combined
)
,
exposure AS
(
SELECT
ProjectID,
TypeID,
DateCreated,
reserve,
spentReserve AS spentNew,
spentProjectType - spentReserve AS spentOld,
CASE WHEN
spentReserve > reserve -- If new spending exceeds the current reserve
THEN -- The the exposure equals total spending to date
spentProjectType -- Otherwise it's the old spent value, plus the reserve
ELSE
spentProjectType - spentReserve + reserve
END
AS exposure
FROM
runningTotal
)
示例SQL:
PID,TID EffectiveDate Exposure Delta
64,4 01/01/2020 1,000 1,000 -- Reserve Added
64,4 03/01/2020 1,000 0 -- Payment Made
64,4 05/01/2020 2,000 1,000 -- Payment Made
64,4 07/01/2020 7,000 5,000 -- Reserve Revised
64,4 09/01/2020 7,000 0 -- Payment Made
64,4 11/01/2020 5,000 -2,000 -- Reserve Revised
64,5 10/01/2020 3,000 3,000 -- Payment Made
64,5 12/01/2020 4,000 1,000 -- Reserve Revised
然后可以按时间顺序交错多个类型,并在整个项目中累加DeltaExposure值...
,
deltaExposure AS
(
SELECT
exposure.*,
exposure.exposure
-
LAG(exposure.exposure, 0)
OVER (PARTITION BY exposure.ProjectID, exposure.TypeID
ORDER BY exposure.DateCreated
)
AS deltaExposure
FROM
exposure
)
示例SQL:
PID,TID EffectiveDate Delta ProjectExposure
64,4 01/01/2020 1,000 1,000 -- Reserve Added
64,4 03/01/2020 0 1,000 -- Payment Made
64,4 05/01/2020 1,000 2,000 -- Payment Made
64,4 07/01/2020 5,000 7,000 -- Reserve Revised
64,4 09/01/2020 0 7,000 -- Payment Made
64,5 10/01/2020 3,000 10,000 -- Payment Made
64,4 11/01/2020 -2,000 8,000 -- Reserve Revised
64,5 12/01/2020 1,000 9,000 -- Reserve Revised
显示需要每天计算的示例:
想象一个由Exp1和Exp2两部分组成的项目。在每个活动日期(每次付款或准备金修订)计算出风险之后,我们将获得以下“ DeltaExposure”值。
,
projectExposure AS
(
SELECT
deltaExposure.*,
SUM(deltaExposure.exposure)
OVER (PARTITION BY deltaExposure.ProjectID
ORDER BY deltaExposure.DateCreated
)
AS projectExposure
FROM
deltaExposure
)
SELECT
ProjectID,
MAX(ProjectExposure) AS MaxProjectExposure
FROM
projectExposure
GROUP BY
ProjectID
最高风险暴露于Exp1上的第二次付款之日。中间支付三;如果不考虑其他所有时间序列,就无法知道Exp1的哪些付款日期是高峰暴露的候选者。