简体   繁体   English

使用Xquery针对递归数据查询?

[英]Query against recursive data using Xquery?

I am needing to perform a hierarchical query that's rather common in SQL. 我需要执行在SQL中相当普遍的分层查询。 But now I need to do the same thing upon an xml document using Xquery. 但是现在我需要使用Xquery对xml文档执行相同的操作。

For an example, I'm modeling off a standard Oracle tutorial on its recursive CONNECT BY feature. 例如,我正在基于其递归CONNECT BY功能对标准Oracle教程进行建模。 This is the table, but converted to xml: 这是表,但转换为xml:

<EMPLOYEES>
  <EMP>
    <EMPNO>7369</EMPNO>
    <ENAME>SMITH</ENAME>
    <JOB>CLERK</JOB>
    <MGR>7902</MGR>
    <HIREDATE>17-DEC-80</HIREDATE>
    <SAL>800</SAL>
  </EMP>
  <EMP>
    <EMPNO>7499</EMPNO>
    <ENAME>ALLEN</ENAME>
    <JOB>SALESMAN</JOB>
    <MGR>7698</MGR>
    <HIREDATE>20-FEB-81</HIREDATE>
    <SAL>1600</SAL>
    <COMM>300</COMM>
  </EMP>
  <EMP>
    <EMPNO>7521</EMPNO>
    <ENAME>WARD</ENAME>
    <JOB>SALESMAN</JOB>
    <MGR>7698</MGR>
    <HIREDATE>22-FEB-81</HIREDATE>
    <SAL>1250</SAL>
    <COMM>500</COMM>
  </EMP>
  <EMP>
    <EMPNO>7566</EMPNO>
    <ENAME>JONES</ENAME>
    <JOB>MANAGER</JOB>
    <MGR>7839</MGR>
    <HIREDATE>02-APR-81</HIREDATE>
    <SAL>2975</SAL>
  </EMP>
  <EMP>
    <EMPNO>7654</EMPNO>
    <ENAME>MARTIN</ENAME>
    <JOB>SALESMAN</JOB>
    <MGR>7698</MGR>
    <HIREDATE>28-SEP-81</HIREDATE>
    <SAL>1250</SAL>
    <COMM>1400</COMM>
  </EMP>
  <EMP>
    <EMPNO>7698</EMPNO>
    <ENAME>BLAKE</ENAME>
    <JOB>MANAGER</JOB>
    <MGR>7839</MGR>
    <HIREDATE>01-MAY-81</HIREDATE>
    <SAL>2850</SAL>
  </EMP>
  <EMP>
    <EMPNO>7782</EMPNO>
    <ENAME>CLARK</ENAME>
    <JOB>MANAGER</JOB>
    <MGR>7839</MGR>
    <HIREDATE>09-JUN-81</HIREDATE>
    <SAL>2450</SAL>
  </EMP>
  <EMP>
    <EMPNO>7788</EMPNO>
    <ENAME>SCOTT</ENAME>
    <JOB>ANALYST</JOB>
    <MGR>7566</MGR>
    <HIREDATE>19-APR-87</HIREDATE>
    <SAL>3000</SAL>
  </EMP>
  <EMP>
    <EMPNO>7839</EMPNO>
    <ENAME>KING</ENAME>
    <JOB>PRESIDENT</JOB>
    <HIREDATE>17-NOV-81</HIREDATE>
    <SAL>5000</SAL>
  </EMP>
  <EMP>
    <EMPNO>7844</EMPNO>
    <ENAME>TURNER</ENAME>
    <JOB>SALESMAN</JOB>
    <MGR>7698</MGR>
    <HIREDATE>08-SEP-81</HIREDATE>
    <SAL>1500</SAL>
    <COMM>0</COMM>
  </EMP>
  <EMP>
    <EMPNO>7876</EMPNO>
    <ENAME>ADAMS</ENAME>
    <JOB>CLERK</JOB>
    <MGR>7788</MGR>
    <HIREDATE>23-MAY-87</HIREDATE>
    <SAL>1100</SAL>
  </EMP>
  <EMP>
    <EMPNO>7900</EMPNO>
    <ENAME>JAMES</ENAME>
    <JOB>CLERK</JOB>
    <MGR>7698</MGR>
    <HIREDATE>03-DEC-81</HIREDATE>
    <SAL>950</SAL>
  </EMP>
  <EMP>
    <EMPNO>7902</EMPNO>
    <ENAME>FORD</ENAME>
    <JOB>ANALYST</JOB>
    <MGR>7566</MGR>
    <HIREDATE>03-DEC-81</HIREDATE>
    <SAL>3000</SAL>
  </EMP>
  <EMP>
    <EMPNO>7934</EMPNO>
    <ENAME>MILLER</ENAME>
    <JOB>CLERK</JOB>
    <MGR>7782</MGR>
    <HIREDATE>23-JAN-82</HIREDATE>
    <SAL>1300</SAL>
  </EMP>
</EMPLOYEES>

I am trying to emulate the SYS_CONNECT_BY_PATH function, and produce the Org hierarchy for a given employee. 我正在尝试模拟SYS_CONNECT_BY_PATH函数,并为给定的员工生成组织层次结构。 eg for employee ADAMS... 例如员工ADAMS ...

KING JONES SCOTT ADAMS 琼斯·斯科特·亚当斯

The linkage is between an emp id and his mgr code. 链接是在empid和他的mgr代码之间。

It looks like a recursive string concatenation function would do the trick, but I'm too new to Xquery and can't get syntax to work. 看起来像递归字符串连接功能可以解决问题,但是我对Xquery还是太陌生,无法使用语法。

Part of my cornfusion stems from the notion of 'Hierachy'. 我的部分融合来自“ Hierachy”的概念。 This is not the document hierachy that I need to chase. 这不是我需要追求的文件层次结构。 The hierarchy is in the data; 层次结构在数据中; rendered more like a linked list. 呈现得更像一个链表。

Any thoughts would be appreciated. 任何想法将不胜感激。

Ideally the XML would be formatted hierarchically, so the organization is implicit in the XML, and all you would need to do is get employee ancestors (or descendants). 理想情况下,XML将进行分层格式化,因此组织在XML中是隐式的,您需要做的就是获取雇员的祖先(或后代)。 In this case, you can write a recursive function that follows the path of ID-based links from employee to manager-employee: 在这种情况下,您可以编写一个递归函数,该函数遵循从雇员到经理雇员的基于ID的链接的路径:

declare function local:boss-R(
  $emp as element(EMP)?
) as xs:string*
{
  if (empty($emp)) then ()
  else 
    let $boss := $emp/ancestor::EMPLOYEES/EMP[EMPNO eq $emp/MGR]
    return ($boss/ENAME/string(), local:boss-R($boss))
};

declare function local:org(
  $emp as element(EMP)
) as xs:string+
{
  $emp/ENAME, local:boss-R($emp)
};

let $emp := doc('employees.xml')/EMPLOYEES/EMP[1]
return reverse(local:org($emp))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM