我有一个复杂的问题需要解决而不使用循环。循环似乎非常简单。但是当试图在基于Set的操作中思考时,它被证明是非常棘手的。
详情
以下是PaymentPlan
表,其中我存储了每个客户的付款计划。
例如:客户将支付多少费用以及支付日期。
PlanId |PaymentAmount |CustomerId |StartDate
100 |200.00 |100 |2017-01-01
200 |100.00 |100 |2017-02-01
300 |100.00 |100 |2017-03-01
400 |200.00 |100 |2017-04-01
如上表所示,它包含customerId 100的所有付款计划。
接下来我有一个名为Transaction
的表。此表存储了上述付款计划的交易。
TransId |CustomerId |Amount |TransactionDate |IsReversed
100 |100 |100.00 |2017-01-01 |0
200 |100 |100.00 |2017-01-02 |0
300 |100 |60.00 |2017-01-04 |0
400 |100 |40.00 |2017-02-02 |0
500 |100 |300.00 |2017-04-02 |0
600 |100 |200.00 |2017-04-10 |1
问题在于PaymentPlan
和Transaction
表之间没有关系,我们无法创建它太复杂且系统是单片的。
我正在尝试创建一个名为TransPaymentPlanMapping
的新表
将以下列格式存储两个表之间的映射。
使用循环创建映射并不困难,但性能不会很好。我无法提出基于集合的解决方案。
CustomerId |transId |PlanId |RunningPaidAmount |transDateTime |IsReversed
100 |100 |100 |100 |2017-01-01 |0
100 |200 |100 |200 |2017-01-02 |0
100 |300 |200 |60 |2017-01-04 |0
100 |400 |200 |100 |2017-02-02 |0
100 |500 |300 |100 |2017-04-02 |0
100 |500 |400 |200 |2017-04-02 |0
100 |600 |400 |-200 |2017-04-10 |1
以下是映射完成的细分方法。
2017-01-01
客户付款$100
,结果为TransId: 100
并且此transId被分配planId 100
。为什么?因为这是
最早的计划。2017-01-02
客户再次付款$100
生成TransId
200
后再次分配到planId 100
。为什么?因为它是
在步骤1中部分支付。planId 100
的总金额为200美元。2017-01-04
客户付款$60
并生成transId: 300
,该planId: 200
已分配给2017-02-02
,因为此付款方案是下一个付款方式。$40
生成此planId: 200
transId: 400
的{{1}}客户付款planId: 200
金额已生成并映射到planId: 300 and 400
。2017-04-02
付款时迟到了$300
他/她决定支付planId: 300 and 400
,这将涵盖transId: 500
。此付款产生1 planId 300 and 400
。但是在映射表中,此事件为2017-04-10
创建了两个条目。2017-04-02
$200
客户卡在planId:400
付款时拒付,PaymentPlan
只会下降。这导致了交易表中的逆转交易。然后,此事务将映射到映射表中的最新条目。如映射表中所示,transaction
现在为-200。以下是用于创建CREATE TABLE #PaymentPlan(PlanId INT ,
PaymentAmount NUMERIC(8,2),
CustomerId INT,
StartDate DATETIME)
INSERT #PaymentPlan(
PlanId ,
PaymentAmount ,
CustomerId ,
StartDate )
VALUES ( 100, 200.00, 100, '2017-01-01'),
( 200, 100.00, 100, '2017-02-01'),
( 300, 100.00, 100, '2017-03-01'),
( 400, 200.00, 100, '2017-04-01')
CREATE TABLE #transaction(TransId INT,
CustomerId INT,
Amount NUMERIC(8,2),
TransactionDate DATETIME,
IsReversed BIT)
INSERT #transaction(
TransId ,
CustomerId ,
Amount ,
TransactionDate ,
IsReversed)
VALUES (100,100,100.00,'2017-01-01',0),
(200,100,100.00,'2017-01-02',0),
(300,100,60.00 ,'2017-01-04',0),
(400,100,40.00, '2017-02-02',0),
(500,100,300.00,'2017-04-02',0),
(600,100,200.00,'2017-04-10',1)
SELECT * FROM #PaymentPlan ORDER BY StartDate
SELECT * FROM #transaction ORDER BY TransactionDate
和if (UIApplication.shared.statusBarOrientation == UIInterfaceOrientation.portrait)
表格的脚本。
<?php foreach($allDiscussion as $data): ?>
<div class="col s12 com_app_count_section">
<script>count_app_and_com('<?=$data->discussion_id?>');</script>
</div>
<?php endforeach; ?>
非常感谢我能得到的任何帮助。
答案 0 :(得分:1)
可以将两个表中的金额表示为连续范围,然后找到重叠范围。下一个snippet可能是更精细版本的基础。
CREATE TABLE #PaymentPlan(PlanId INT,
PaymentAmount NUMERIC(8, 2),
CustomerId INT,
StartDate DATETIME);
INSERT #PaymentPlan(
PlanId,
PaymentAmount,
CustomerId,
StartDate)
VALUES ( 100, 200.00, 100, '2017-01-01'),
( 200, 100.00, 100, '2017-02-01'),
( 300, 100.00, 100, '2017-03-01'),
( 400, 200.00, 100, '2017-04-01');
CREATE TABLE #transaction(TransId INT,
CustomerId INT,
Amount NUMERIC(8,2),
TransactionDate DATETIME,
IsReversed BIT);
INSERT #transaction(
TransId,
CustomerId,
Amount,
TransactionDate,
IsReversed)
VALUES (100,100,100.00,'2017-01-01',0),
(200,100,100.00,'2017-01-02',0),
(300,100,60.00 ,'2017-01-04',0),
(400,100,40.00, '2017-02-02',0),
(500,100,200.00,'2017-04-02',0),
(600,100,300.00,'2017-04-10',1);
WITH
p AS (
SELECT *,
SUM(PaymentAmount) OVER(PARTITION BY CustomerId ORDER BY StartDate) - PaymentAmount LeftBound,
SUM(PaymentAmount) OVER(PARTITION BY CustomerId ORDER BY StartDate) RightBound
FROM #PaymentPlan
),
t AS (
SELECT *,
SUM(Amount) OVER(PARTITION BY CustomerId ORDER BY TransactionDate) - Amount LeftBound,
SUM(Amount) OVER(PARTITION BY CustomerId ORDER BY TransactionDate) RightBound
FROM #transaction
)
SELECT
t.CustomerId, t.TransId, p.PlanId,
p.LeftBound PlanLeftBound, p.RightBound PlanRightBound,
t.LeftBound TransLeftBound, t.RightBound TransRightBound,
t.TransactionDate transDateTime, t.IsReversed
FROM p JOIN t
ON p.CustomerId = t.CustomerId AND
p.LeftBound < t.RightBound AND
p.RightBound > t.LeftBound;