Xml PostgreSQL Xpath来选择元素和它';将子属性设置为两列
我在postgreSQL中有一个表历史记录(id int,content xml)。其中一个id的XML内容如下所示Xml PostgreSQL Xpath来选择元素和它';将子属性设置为两列,xml,postgresql,xpath,Xml,Postgresql,Xpath,我在postgreSQL中有一个表历史记录(id int,content xml)。其中一个id的XML内容如下所示 <history-data> <history recorded-date="20110601"> <assignees> <assignee> <last-name>CIENA LUXEMBOURG</last-name>
<history-data>
<history recorded-date="20110601">
<assignees>
<assignee>
<last-name>CIENA LUXEMBOURG</last-name>
</assignee>
</assignees>
<assignors>
<assignor execution-date="20110517">
<last-name>NORTEL NETWORKS LIMITED</last-name>
</assignor>
</assignors>
</history>
<history recorded-date="20110601">
<assignees>
<assignee>
<last-name>CIENA CORPORATION</last-name>
</assignee>
</assignees>
<assignors>
<assignor execution-date="20110527">
<last-name>CIENA LUXEMBOURG</last-name>
</assignor>
</assignors>
</history>
<history recorded-date="20090430">
<assignees>
<assignee>
<last-name>NORTEL NETWORKS</last-name>
</assignee>
</assignees>
<assignors>
<assignor execution-date="20090424">
<last-name>MAK, GARY</last-name>
</assignor>
<assignor execution-date="20090424">
<last-name>VELEZ, EDGAR</last-name>
</assignor>
</assignors>
</history>
</history-data>
我能够使用下面的SQL查询生成所有可能的组合,但无法获得上面那样的输出
SELECT id, unnest(CAST(xpath('/history-data/history/assignees/assignee/last-name/text()',content) AS text)::text[]) AS last-name,
unnest(CAST(xpath('/history-data/history/assignors/assignor/@execution-date',content) AS text)::text[]) AS execution-date
FROM history
WHERE id = 10
有什么建议可以这样做吗?您的请求所做的是找到所有的受让人,并独立地找到所有的执行日期,然后返回笛卡尔积,这可能不是您真正想要的 你想要的是:
- 查找所有
元素历史记录
- 然后,针对每个
历史
元素,找到您感兴趣的文本/属性
SELECT
unnest(xpath('./assignees/assignee/last-name/text()',item))::text,
unnest(xpath('./assignors/assignor/@execution-date',item))::text
FROM (
SELECT
unnest(xpath('/history-data/history',content)) AS item
FROM history
WHERE id = 10
) s
GROUP BY 1,2;
请注意,如果在一个历史
元素中有多个受让人
s,则可能会得到奇怪的结果。另外,不确定您是想要所有的执行日期
s,还是只想要第一个、最后一个或
编辑
要获取所有受让人
s,但仅列出第一个执行日期
:
SELECT
unnest(xpath('./assignees/assignee/last-name/text()',item))::text,
(xpath('./assignors/assignor/@execution-date',item))[1]::text
FROM (
SELECT
unnest(xpath('/history-data/history',content)) AS item
FROM history
WHERE id = 10
) s
GROUP BY 1,2;
您需要迭代所有
历史
节点,并使用函数获取适当的元素。默认情况下,xpath提取的结果返回xml数组,这就是为什么我们需要使用数组索引(…)[1]
获取实际值;示例查询可能如下所示:
SELECT
(xpath('//assignee/last-name/text()',xml_element))[1] AS "last-name",
(xpath('//assignor/@execution-date',xml_element))[1] AS "execution-date"
FROM (
SELECT unnest(xpath('//history',content)) AS xml_element FROM history
WHERE id = 10
) t;
结果是:
last-name | execution-date
-------------------+----------------
CIENA LUXEMBOURG | 20110517
CIENA CORPORATION | 20110527
NORTEL NETWORKS | 20090424
(3 rows)
版本
当assignees
具有多个assagene
节点时,查询应使用unnest()
获取所有数组元素:
SELECT
unnest(xpath('//assignee/last-name/text()',xml_element)) AS "last-name",
unnest(xpath('//assignor/@execution-date',xml_element)) AS "execution-date"
FROM (
SELECT unnest(xpath('//history',content)) AS xml_element FROM history
WHERE id = 10
) t;
非常感谢。这可以很好地工作,但当我有多个受让人&在单个历史记录中只有一个受让人时,它不会给出正确的结果。在这种情况下,我希望获得具有相同执行日期的两个受让人。你知道怎么做吗?当你有多个
assignee
@GainiRajeshwarThank的条目时,只需使用unnest()
。是的,当有一个受让人时,这可以正常工作。即使在一个历史元素中有多个受让人,我也希望这样做有效。在这种情况下,我希望列出所有具有第一个执行日期(如果在单个历史记录中有多个转让人和执行日期)的受让人的第一个日期,或者按时间顺序列出第一个日期(如果有差异)?@jacron first datelisted@jacron谢谢你。但GroupBy在这里不能处理xml元素。您必须将其转换为文本或任何其他数据类型。相应地更新了答案。
SELECT
unnest(xpath('//assignee/last-name/text()',xml_element)) AS "last-name",
unnest(xpath('//assignor/@execution-date',xml_element)) AS "execution-date"
FROM (
SELECT unnest(xpath('//history',content)) AS xml_element FROM history
WHERE id = 10
) t;