【问题标题】:PostgreSQL - How to render MORE one to many relationships to XMLPostgreSQL - 如何将更多的一对多关系呈现给 XML
【发布时间】:2014-07-25 02:30:49
【问题描述】:

我想从我的数据库的三个表中创建 XML 导出。

表格:客户、订单、付款。当然,一位客户可能有更多订单和更多付款。

我已经在 stackoverflow 上看到了这个很棒的主题:“How to render one to many relationships to XML with PostgreSQL",这对我了解如何构建查询很有帮助。但是,那里的说明仅在我将表客户加入订单或付款,而不是他们两个。我没有找到如何构建查询,所以我在模型中得到了这样的输出:

<Customer>
<Name/>
<Orders>
    <Order>
        <id/>
        <date/>
        <content/>
    </Order>
</Orders>
<Payments>
    <Payment>
        <id/>
        <date/>
        <amount/>
    </Payment>
</Payments>
</Customer>

尝试这样做:

SELECT xmlelement(name "Customer",
                    xmlelement(name "Name", c.name),
       xmlelement(name "Orders",
             xmlagg(xmlelement(name "Order",
                        xmlelement(name "id", o.id),                    
                        xmlelement(name "date", o.date),
                        xmlelement(name "content", o.content)))),
       xmlelement(name "Payments",                          
             xmlagg(xmlelement(name "Payment",
                        xmlelement(name "id", p.id),                        
                        xmlelement(name "date", p.date),
                        xmlelement(name "amount", p.amount)))))
from customers c
left join orders o on c.id = o.c_id
left join payments p on c.id = p.c_id
group by c.id, c.name;

...没有意义。例如,如果客户有 5 个订单和 3 个付款,它会返回包含 15 行的表。所以有 15 个订单和 15 个付款。我不知道如何以正确的方式使用 xmlaagg() 函数。作为使用 XML 的新手,我什至不知道是否有可能以所需的方式从数据库创建输出。

我将非常感谢任何帮助。

样本数据: (这只是一个简单的例子。假设订单和付款之间没有关系。在我的实际项目中,还有其他项目,它们没有关系。我需要查看所有付款和所有订单。)

CREATE TEMPORARY TABLE customers
(
    id      int,
    name    text
);

CREATE TEMPORARY TABLE orders
(
    id      int,
    c_id    int, -- customer ID
    date    date,
    content text

);

CREATE TEMPORARY TABLE payments
(
    id      int,
    c_id    int, -- customer ID
    date    date,
    amount  numeric
);

INSERT INTO customers
VALUES(1, 'someguy');

INSERT INTO orders
VALUES
(1, 1, '1.1.2001', 'noteboook'),
(2, 1, '2.1.2001', 'tablet'),
(3, 1, '3.1.2001', 'phone'),
(4, 1, '3.1.2001', 'bag'),
(5, 1, '3.1.2001', 'shoes');

INSERT INTO payments
VALUES
(1, 1, '1.2.2001', '100'),
(2, 1, '2.2.2001', '200'),
(3, 1, '3.2.2001', '300');  

-- DROP TABLE payments;
-- DROP TABLE orders;
-- DROP TABLE customers;

【问题讨论】:

  • 嗯,肯定会的。但不幸的是,我目前只能应付 SQL。我知道,是时候学习一些编程语言了。
  • 对不起,出于某种原因,我认为您使用的是 Ruby 之类的东西。今天看了太多该标签中的其他帖子,对不起。忽略我的评论。
  • 感谢您的反应!
  • 请将示例数据显示为创建表和插入语句。没有它就很难编写和测试任何东西来帮助你。
  • 好的,我一会儿再做。

标签: sql xml postgresql aggregate-functions outer-join


【解决方案1】:

join前需要聚合

select
    xmlelement(name "Customer",
        xmlelement(name "Name", name),
        orders, payments
    ) as the_xml
from
    customers
    left join (
        select c_id as id,
        xmlelement(name "Orders",
            xmlagg(xmlelement(name "Order",
                xmlelement(name "id", id),                    
                xmlelement(name "date", date),
                xmlelement(name "content", content)
                )
            )
        ) as orders
        from orders
        group by c_id
    ) o using (id)
    left join (
        select c_id as id,
        xmlelement(name "Payments",                          
            xmlagg(xmlelement(name "Payment",
                xmlelement(name "id", id),                        
                xmlelement(name "date", date),
                xmlelement(name "amount", amount)
                )
            )
        ) as payments
        from payments
        group by c_id
    ) p using (id)

【讨论】:

  • 哇哦!!!惊人的!非常感谢,我自己永远找不到解决方案,可能,我以前很努力,但现在对我来说似乎很清楚!你帮了我很多,干杯!
猜你喜欢
  • 2012-12-08
  • 2012-04-05
  • 2011-02-11
  • 2012-08-22
  • 2012-06-22
  • 2015-02-06
  • 2023-03-29
  • 1970-01-01
  • 2022-01-23
相关资源
最近更新 更多