【问题标题】:xquery -nested for with variablexquery - 嵌套用于变量
【发布时间】:2013-11-29 18:45:12
【问题描述】:

我有这个 xml

<Edu>
<Department>
 <Student>
  <name>jack</name>
  <Std_ID>12345678</Std_ID>
  <Degree>MS</Degree>
   </Student>
   <Student>
  <name>melin</name>
  <Std_ID>56784921</Std_ID>
  <Degree>PHD</Degree>
   </Student>

    <Student>
  <name>sali</name>
  <Std_ID>54673821</Std_ID>
  <Degree>MS</Degree>
   </Student>
   <Student>
  <name>parisa</name>
  <Std_id>54321876</Std_id>
  <Degree>BS</Degree>
  </Student> 

  <Student>
   <name>caty</name>
   <Std_ID>87654321</Std_ID>
   <Degree>MS</Degree>
  </Student> 


</Department>
<Course>
<name>programing</name>
<Student>
<name>jack</name>
<Std_ID>12345678</Std_ID>
<Degree>MS</Degree>
 </Student>
 <Student>
  <name>sali</name>
  <Std_ID>54673821</Std_ID>
  <Degree>MS</Degree>
   </Student>

<Student>
<name>parisa</name>
<Std_id>54321876</Std_id>
<Degree>BS</Degree>
</Student> 
</Course>
<Course>
<name>network</name>
 <Student>
 <name>jack</name>
 <Std_ID>12345678</Std_ID>
 <Degree>MS</Degree>
 </Student>
 </Course>
 <Course>
 <name>Database</name>

 <Student>
  <name>jack</name>
  <Std_ID>12345678</Std_ID>
  <Degree>MS</Degree>
 </Student>

 <Student>
  <name>caty</name>
  <Std_ID>87654321</Std_ID>
  <Degree>MS</Degree>
 </Student> 
 </Course>
  <Course>

  <Student>
  <name>jack</name>
  <Std_ID>12345678</Std_ID>
  <Degree>MS</Degree>
   </Student>

  <Student>
   <name>caty</name>
   <Std_ID>87654321</Std_ID>
   <Degree>MS</Degree>
  </Student>   
  </Course>
  </Edu>

我想列出拥有超过 2 门课程的 MS 学位的学生,或拥有超过 1 门课程的 BS 学生。我的意思是我想要拥有超过 2 门课程的 MS 学位的学生或拥有超过一门课程的学士学位的学生的姓名。我想要这两个列表。 这是我的 xquery:但它不起作用:

for $i in doc("XMLFile_Q2.xml")/Edu/Department/Student[Degree="MS" or Degree="BS"]
let $counter :=0
for $a in doc("XMLFile_Q2.xml")/Edu/Course
where $a/Student[name]=$i[name] 
 let $counter := $counter+1
  return if($a/Student[Degree]="MS" and $counter gt 2 )
    then  $a/Student/name
    else if($a/Student[Degree]="BS" and $counter gt 1)
    then $a/Student/name/text()
    else()

【问题讨论】:

标签: xquery


【解决方案1】:

首先也是最重要的:您的代码(或至少大部分代码)在命令式语言中是完全正常的,但 XQuery 是一种函数式语言。您不会通过遍历列表并递增计数器来计算 jack 或 melin 注册的课程数量。在函数式语言中,变量是不可变的。您创建一个表达式,在评估时会产生您想要的答案。以声明的方式思考。

其次,了解谓词(XPath 表达式中方括号括起来的部分)不是记录中的字段或对象中的成员的访问器。不要写$a/Student[name] 你的意思是$a/Student/name

第三,修改语法:在 FLWOR 表达式中,where 子句后面不能跟另一个 let 子句。 forlet 子句共同构建了一个名称/值对元组,然后 where 子句对其进行过滤。

您想要一份满足特定条件的所有 MS 和 BS 学生的列表。首先列出 MS 和 BS 学生:

for $student in doc(...)/Edu/Department
                /Student[Degree = ('MS', 'BS')]
return $student/name

接下来,您要过滤该列表以包括拥有两门以上课程的 MS 学生或拥有多门课程的 BS 学生,并排除其他学生。所以你想要大致像这样的东西:

for $student in doc(...)/Edu/Department
                /Student[Degree = ('MS', 'BS')]
...
where ($student/Degree = 'MS' and count($courses) gt 2)
      or 
      ($student/Degree = 'BS' and count($courses) gt 1)
return $student/name (: or perhaps just $student :)

所以现在骨架有一个 ... 我们需要将变量 $courses 绑定到当前 $student 注册的课程集。以下let 表达式将执行此操作:

let $course := doc(...)/Edu/Course[Student/name = $student/name]

生成的查询有点笨拙和重复,所以在现实生活中我会分解出更多的常用表达式并产生如下内容:

for $student in $doc/Department/Student
let $degree := $student/Degree/string(),
    $name := $student/name,
    $courses := $doc/Course[Student/name = $name],
    $coursecount := count($courses)
where ($degree = 'MS' and $coursecount gt 2)
      or 
      ($degree = 'BS' and $coursecount gt 1)
return <student name="{$name}" 
                degree="{$degree}" 
                courses="{$coursecount}"/>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-11
    • 2018-11-14
    • 1970-01-01
    相关资源
    最近更新 更多