Вложение XMLAgg()
вызовов немного сложно, но вы можете сделать это в два этапа; сначала получите каждый ID / срок / вид / сумму со списком связанных платежей:
select id, due_date, kind, unpaid_amount, required_amount,
xmlagg(xmlelement("related-payment",
xmlforest(received as "received", entered as "entered", paid_amount as "amount")))
from your_table
group by id, due_date, kind, unpaid_amount, required_amount;
, который с вашими примерами данных (с фрагментом XMl, сериализованным для читабельности):
ID DUE_DATE KIND UNPAID_AMOUNT REQUIRED_AMOUNT XMLSERIALIZE(CONTENTXMLAGG(XMLELEMENT("RELATED-PAYMENT",XMLFOREST(RECEIVEDAS"REC
---------- ---------- ---------- ------------- --------------- --------------------------------------------------------------------------------
9331779 2017-08-11 11 606.42 <related-payment>
<received>2017-07-17</received>
<entered>2017-07-18</entered>
<amount>127.59</amount>
</related-payment>
<related-payment>
<received>2017-09-15</received>
...
, а затем использовать его в качестве встроенного представления для второго уровня агрегации:
select
xmlelement("payment-list",
xmlagg(
xmlelement("payment",
xmlforest(kind as "kind",
to_char(due_date, 'YYYY-MM-DD') as "due",
nvl(unpaid_amount, 0) as "amount",
nvl(required_amount, 0) as "waiting",
related_payments as "related-payment-list"
)
)
)
) as result
from (
select id, due_date, kind, unpaid_amount, required_amount,
xmlagg(
xmlelement("related-payment",
xmlforest(received as "received",
entered as "entered",
paid_amount as "amount"
)
)
) as related_payments
from your_table
group by id, due_date, kind, unpaid_amount, required_amount
);
Демонстрация с вашими примерами данных в виде CTE и добавлением сериализации для удобства чтения:
-- CTE for sample data
with your_table (id, due_date, kind, unpaid_amount, required_amount, paid_amount, received, entered) as (
select 9331779, date '2017-08-11', 11, null, 606.42, 127.59, date '2017-07-17', date '2017-07-18' from dual
union all select 9331779, date '2017-08-11', 11, null, 606.42, 446.81, date '2017-08-16', date '2017-08-17' from dual
union all select 9331779, date '2017-08-11', 11, null, 606.42, 32.02, date '2017-09-15', date '2017-09-18' from dual
union all select 9331782, date '2017-11-11', 11, null, 606.42, 95.57, date '2017-11-15', date '2017-11-16' from dual
union all select 9331782, date '2017-11-11', 11, null, 606.42, 446.81, date '2017-12-15', date '2017-12-18' from dual
union all select 9331782, date '2017-11-11', 11, null, 606.42, 64.04, date '2018-01-03', date '2018-01-04' from dual
)
-- actual query
select xmlserialize(document
xmlelement("payment-list",
xmlagg(
xmlelement("payment",
xmlforest(kind as "kind",
to_char(due_date, 'YYYY-MM-DD') as "due",
nvl(unpaid_amount, 0) as "amount",
nvl(required_amount, 0) as "waiting",
related_payments as "related-payment-list"
)
)
)
)
indent size=2) as result
from (
select id, due_date, kind, unpaid_amount, required_amount,
xmlagg(
xmlelement("related-payment",
xmlforest(received as "received",
entered as "entered",
paid_amount as "amount"
)
)
) as related_payments
from your_table
group by id, due_date, kind, unpaid_amount, required_amount
);
, который получает:
RESULT
--------------------------------------------------------------------------------
<payment-list>
<payment>
<kind>11</kind>
<due>2017-08-11</due>
<amount>0</amount>
<waiting>606.42</waiting>
<related-payment-list>
<related-payment>
<received>2017-07-17</received>
<entered>2017-07-18</entered>
<amount>127.59</amount>
</related-payment>
<related-payment>
<received>2017-09-15</received>
<entered>2017-09-18</entered>
<amount>32.02</amount>
</related-payment>
<related-payment>
<received>2017-08-16</received>
<entered>2017-08-17</entered>
<amount>446.81</amount>
</related-payment>
</related-payment-list>
</payment>
<payment>
<kind>11</kind>
<due>2017-11-11</due>
<amount>0</amount>
<waiting>606.42</waiting>
<related-payment-list>
<related-payment>
<received>2017-11-15</received>
<entered>2017-11-16</entered>
<amount>95.57</amount>
</related-payment>
<related-payment>
<received>2018-01-03</received>
<entered>2018-01-04</entered>
<amount>64.04</amount>
</related-payment>
<related-payment>
<received>2017-12-15</received>
<entered>2017-12-18</entered>
<amount>446.81</amount>
</related-payment>
</related-payment-list>
</payment>
</payment-list>