sql支付分发
Posted
技术标签:
【中文标题】sql支付分发【英文标题】:sql payment distribution 【发布时间】:2017-02-08 22:17:30 【问题描述】:我正在寻找一个查询,其中根据 account_num 和 item_order 将一定金额分配到下面的每张发票。此外,如果 partial_payment_allowed 设置为“N”,则仅当分配的金额大于 invoice_amt 时才应分配上述金额,否则应跳过该行并继续到帐户的下一张发票。
Item_order inv_amount Partial_pmt account_num cr_amt
1 1256 Y 12 1000
2 1134 Y 12 1000
1 800 Y 13 1200
2 200 N 13 1200
3 156 N 13 1200
在上面的数据中,每个账户都有一个cr_amt,可以根据item_order进行分配。所以分配后的结果是
account_num Item_order inv_amount Partial_pmt Dist_amt Bal_amt
12 1 1256 Y 1000 256
12 2 1134 Y 256 878
13 1 800 Y 800 400
13 2 200 N 200 200
13 3 156 N 100 100
我们正在努力避免循环,非常感谢任何 cmet。谢谢。
【问题讨论】:
仅当 dist_amt > inv_amount 时才付款。 1000 抱歉,mike,修复了部分 pmt 标志。请立即检查。 @mathguy 他在评论中问了一个后续问题。在这个版本中,他需要对每个不同的account_num
进行单独计算。我不能很容易地理解他从他的评论帖子中问了什么,所以我问了他一个单独的问题。我希望那不是犯规。
哦-好的。但这应该在新帖子(此处)中明确说明。
在旧问题中,我们没有多个帐户具有一定的分配金额。我尝试通过使用分区来解决 sql 模型子句,但是当引入多个帐户时查询会分崩离析。我只是在寻找任何其他方法来解决这个问题。很抱歉给您带来不便,如果您仍然认为这是重复,我将删除此帖子。谢谢
【参考方案1】:
扩展这个问题的答案: payment distrubution oracle sql query
您仍然可以使用 SQL MODEL
子句。在此版本中,您需要对每个不同的account_num
进行单独计算。您可以使用 SQL MODEL
子句的 PARTITION
关键字来实现此目的,以通过 account_num
进行分区。
像这样(请参阅 SQL cmets 以获取分步说明):
-- Set up test data (since I don't have your table)
WITH inv_raw (item_order, inv_amount, partial_pmt_allowed, account_num, cr_amt) AS (
SELECT 1, 1256, 'Y', 12, 1000 FROM DUAL UNION ALL
SELECT 2, 1134, 'Y', 12, 1000 FROM DUAL UNION ALL
SELECT 3, 800, 'Y', 13, 1200 FROM DUAL UNION ALL
SELECT 4, 200, 'N',13, 1200 FROM DUAL UNION ALL
SELECT 5, 156, 'N',13, 1200 FROM DUAL),
-- Ensure that the column we are ordering by is densely populated
inv_dense (dense_item_order, item_order, inv_amount, partial_pmt_allowed, account_num, cr_amt) AS
( SELECT DENSE_RANK() OVER ( PARTITION BY account_num ORDER BY item_order ), item_order, inv_amount, partial_pmt_allowed, account_num, cr_amt FROM inv_raw )
-- Give us a way to input the payment amount
--param AS ( SELECT 1100 p_payment_amount FROM DUAL )
-- The actual query starts here
SELECT
account_num,
item_order,
inv_amount,
partial_pmt_allowed,
applied dist_amount,
remaining_out balance_amt,
cr_amt
FROM inv_dense
MODEL
-- We want a completely separate calculation for each distinct account_num
PARTITION BY ( account_num )
-- We'll output one row for each value of dense_item_order.
-- We made item_order "dense" so we can do things like CV()-1 to get the
-- previous row's values.
DIMENSION BY ( dense_item_order )
MEASURES ( cr_amt, item_order, inv_amount,
partial_pmt_allowed, 0 applied,
0 remaining_in, 0 remaining_out )
RULES AUTOMATIC ORDER (
-- The amount carried into the first row is the payment amount
remaining_in[1] = cr_amt[1],
-- The amount carried into subsequent rows is the amount we carried out of the prior row
remaining_in[dense_item_order > 1] = remaining_out[CV()-1],
-- The amount applied depends on whether the amount remaining can cover the invoice
-- and whether partial payments are allowed
applied[ANY] = CASE WHEN remaining_in[CV()] >= inv_amount[CV()] OR partial_pmt_allowed[CV()] = 'Y' THEN LEAST(inv_amount[CV()], remaining_in[CV()]) ELSE 0 END,
-- The amount we carry out is the amount we brought in minus what we applied
remaining_out[ANY] = remaining_in[CV()] - applied[CV()]
)
ORDER BY account_num, item_order;
【讨论】:
以上是关于sql支付分发的主要内容,如果未能解决你的问题,请参考以下文章