将表数据转换为XML

时间:2019-01-02 10:54:11

标签: sql xml oracle

我有这样的数据:

        ID DUE_DATE         KIND UNPAID_AMOUNT REQUIRED_AMOUNT PAID_AMOUNT RECEIVED   ENTERED   
---------- ---------- ---------- ------------- --------------- ----------- ---------- ----------
   9331779 2017-08-11         11                        606.42      127.59 2017-07-17 2017-07-18
   9331779 2017-08-11         11                        606.42      446.81 2017-08-16 2017-08-17
   9331779 2017-08-11         11                        606.42       32.02 2017-09-15 2017-09-18
   9331782 2017-11-11         11                        606.42       95.57 2017-11-15 2017-11-16
   9331782 2017-11-11         11                        606.42      446.81 2017-12-15 2017-12-18
   9331782 2017-11-11         11                        606.42       64.04 2018-01-03 2018-01-04

我想将其转换为XML数据,如下所示:

 <payment-list>
    <payment>
      <kind>11</kind>
      <due>2017-08-11</due>
      <amount>null/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-08-16</received>
          <entered>2017-08-17</entered>
          <amount>446.81</amount>
        </related-payment>
       <related-payment>...
      </related-payment-list>
    </payment>
    <payment>
      <kind>11</kind>
      <due>2017-11-11</due>
      <amount>null/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>2017-12-15</received>
          <entered>2017-12-18</entered>
          <amount>446.81</amount>
        </related-payment>
       <related-payment>...
      </related-payment-list>
    </payment>
 <payment-list>

可以在单个查询中完成吗?我有一个想法/方法可以循环执行,但也许有人使用XMLAgg等有其他想法。

1 个答案:

答案 0 :(得分:1)

嵌套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>