我正在寻找一个查询,其中根据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
我们正在努力避免循环,任何评论都非常感谢。谢谢。
答案 0 :(得分:1)
扩展这个问题的答案: payment distrubution oracle sql query
您仍然可以使用SQL MODEL
子句。在此版本中,您需要为每个不同的account_num
单独计算。您可以使用SQL PARTITION
子句的MODEL
关键字来实现此目的,以account_num
进行分区。
像这样(请参阅SQL注释以获得逐步说明):
-- 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;