我一直把头发拉过来(剩下的就是这样),并且想知道你是否在Oracle的XPath逻辑中看到了我没有看到的东西。我通过Oracle的文档研究了各种函数和XPath方法无济于事。
在下面的示例中,表pg_xml_stg包含属性pressganey_xml(XMLType)。以下内容示例:
<PATIENTLEVELDATA>
<SURVEY_ID>826434950</SURVEY_ID>
<CLIENT_ID>7145</CLIENT_ID>
<SERVICE>IN</SERVICE>
<RECDATE>2014-11-26</RECDATE>
<DISDATE>2014-07-04</DISDATE>
<ANALYSIS>
<RESPONSE>
<VARNAME>A1</VARNAME>
<VALUE>5</VALUE>
这是一个将数据下拉到响应级别的查询,但不包括来自患者级别(survey_id)的数据。不确定我的XPATH字符串是否已关闭或实际的xmlsequence调用是否实际上不会将数据拉到ANALYSIS上面。
SELECT extractvalue (Value (pg), '//VARNAME/text()') as PG_VARNAME
,extractvalue (Value (pg), '//VALUE/text()') as PG_VARNAME
,extractvalue (Value (pg), '../../SURVEY_ID/text()') as PG_VARNAME
FROM v500.pg_xml_stg
,TABLE (xmlsequence (extract (pressganey_xml, '//PATIENTLEVELDATA/ANALYSIS/RESPONSE'))) pg
PG_VARNAME PG_VARNAME PG_VARNAME
A1 5
A2 5
D1 5
D2 5
D3 5
I1 5
I17 5
I6 5
我可以通过索引VARRAY来获得下面的查询,但它不允许超出1级的任何内容。
SELECT extractvalue (Value (pg), '//PATIENTLEVELDATA/SURVEY_ID/text()') as PG_SURVEY_ID
,extractvalue (Value (pg), '//PATIENTLEVELDATA/ANALYSIS[1]/RESPONSE[1]/VARNAME[1]/text()') as PG_VARNAME
,extractvalue (Value (pg), '//PATIENTLEVELDATA/ANALYSIS[1]/RESPONSE[1]/VALUE[1]/text()') as PG_VALUE
FROM v500.pg_xml_stg
, TABLE (xmlsequence (extract (pressganey_xml, '*/PATIENTLEVELDATA'))) pg
PG_SURVEY_ID PG_VARNAME PG_VALUE
826434950 A1 5
830145105 A1 5
842152499 A1 4
846003814 A1 5
850619251 D1 3
850711623 A1 4
851482310 A1 5
谢谢,
布赖恩
答案 0 :(得分:0)
在您的第一个查询中,调查ID不可用,因为pg
仅包含回复;原始XML中的数据不能用于extractvalue()
次调用,因为它没有通过。你正在做的是类似于将值的substr传递给函数并期望函数知道整个原始字符串。
在第二个查询中,您只需指定每个节点名称的第一个实例,如您所知。并且因为每个级别都有多个节点,所以无论如何都不能使用extractvalue()
,尝试获取多个节点会抛出ORA-19025: EXTRACTVALUE returns value of only one node
。而且extractvalue()
is deprecated无论如何。
要获取多个值,您可以使用the XMLTable()
function将XML层次结构转换为更像关系数据的内容。
您的XML代码段不会显示整个结构或节点如何重复,但是从您的查询及其结果向后工作,这样的事情可能足够接近以获得一般性的想法:
<?xml version="1.0"?>
<DATA>
<PATIENTLEVELDATA>
<SURVEY_ID>826434950</SURVEY_ID>
<CLIENT_ID>7145</CLIENT_ID>
<SERVICE>IN</SERVICE>
<RECDATE>2014-11-26</RECDATE>
<DISDATE>2014-07-04</DISDATE>
<ANALYSIS>
<RESPONSE>
<VARNAME>A1</VARNAME>
<VALUE>5</VALUE>
</RESPONSE>
<RESPONSE>
<VARNAME>A2</VARNAME>
<VALUE>6</VALUE>
</RESPONSE>
<RESPONSE>
<VARNAME>D1</VARNAME>
<VALUE>7</VALUE>
</RESPONSE>
</ANALYSIS>
<ANALYSIS>
<RESPONSE>
<VARNAME>A1</VARNAME>
<VALUE>8</VALUE>
</RESPONSE>
<RESPONSE>
<VARNAME>A2</VARNAME>
<VALUE>9</VALUE>
</RESPONSE>
<RESPONSE>
<VARNAME>D1</VARNAME>
<VALUE>10</VALUE>
</RESPONSE>
</ANALYSIS>
</PATIENTLEVELDATA>
<PATIENTLEVELDATA>
<SURVEY_ID>830145105</SURVEY_ID>
<CLIENT_ID>7146</CLIENT_ID>
<SERVICE>IN</SERVICE>
<RECDATE>2014-11-27</RECDATE>
<DISDATE>2014-07-04</DISDATE>
<ANALYSIS>
<RESPONSE>
<VARNAME>A1</VARNAME>
<VALUE>3</VALUE>
</RESPONSE>
<RESPONSE>
<VARNAME>A2</VARNAME>
<VALUE>4</VALUE>
</RESPONSE>
<RESPONSE>
<VARNAME>D1</VARNAME>
<VALUE>7</VALUE>
</RESPONSE>
</ANALYSIS>
<ANALYSIS>
<RESPONSE>
<VARNAME>A1</VARNAME>
<VALUE>11</VALUE>
</RESPONSE>
</ANALYSIS>
</PATIENTLEVELDATA>
</DATA>
然后是这样的查询:
select x.*
from pg_xml_stg pxs
cross join xmltable('for $i in //PATIENTLEVELDATA, $j in $i/ANALYSIS/RESPONSE
return <tmp
pg_survey_id="{$i/SURVEY_ID}"
pg_varname="{$j/VARNAME}"
pg_value="{$j/VALUE}"
/>'
passing pxs.pressganey_xml
columns
pg_survey_id number path '/tmp/@pg_survey_id',
pg_varname varchar2(10) path '/tmp/@pg_varname',
pg_value number path '/tmp/@pg_value'
) x;
获取输出:
PG_SURVEY_ID PG_VARNAME PG_VALUE
------------ ---------- ----------
826434950 A1 5
826434950 A2 6
826434950 D1 7
826434950 A1 8
826434950 A2 9
826434950 D1 10
830145105 A1 3
830145105 A2 4
830145105 D1 7
830145105 A1 11
10 rows selected
它的所有响应VARNAME
/ VALUE
与其父节点相对应&#39; SURVEY_ID
。
XPath使用$i
来获取PATIENTLEVEL
节点,然后在$j
内获取与每个节点相关的RESPONSE
节点,从而展平数据。您感兴趣的值将合并为tmp
子句中虚拟return
节点的属性;为每个响应生成类似的内容:
<tmp pg_survey_id="826434950" pg_varname="A1" pg_value="5" />
passing
子句刚刚从表中标识了XMLType列,并将其传递给XPath。并且columns
子句将虚拟tmp
节点中的属性转换为关系列。
我猜测调查ID和响应值都是数字,但您可以调整所有这些数据类型以匹配您真正拥有的数据类型。