簡體   English   中英

為什么這個XQuery過濾器會返回不需要的元素?

[英]Why does this XQuery filter return unwanted elements?

我正在使用實現XQuery 3.1的BaseX 8.4.1

我試圖在XQuery中做一個非常基本的事情,但我似乎無法弄明白。

我創建了一些示例數據來說明我想要做的事情。 我的數據集看起來像這樣。 它是一個簡單的嵌入式結構。 有幾天,每天都有一些活動,活動有會員。

數據

<root>
    <day>
        <name>1</name>
        <event>
            <name>1</name>
            <member>A</member>
            <member>B</member>
        </event>
        <event>
            <name>2</name>
            <member>C</member>
        </event>
    </day>
    <day>
        <name>2</name>
        <event>
            <name>3</name>
            <member>A</member>
            <member>B</member>
        </event>
        <event>
            <name>4</name>
            <member>C</member>
        </event>
    </day>
    <day>
        <name>3</name>
        <event>
            <name>5</name>
            <member>C</member>
        </event>
    </day>
</root>

我想要做的是獲取一個成員列表,並為每個成員獲取他們有事件的日期列表,以及他們擁有的事件。 所以結果應該是這樣的:

期望的結果

<member>
  <name>A</name>
  <day>
    <name>1</name>
    <event>
      <name>1</name>
      <member>A</member>
      <member>B</member>
    </event>
  </day>
  <day>
    <name>2</name>
    <event>
      <name>3</name>
      <member>A</member>
      <member>B</member>
    </event>
  </day>
</member>
<member>
  <name>B</name>
  <day>
    <name>1</name>
    <event>
      <name>1</name>
      <member>A</member>
      <member>B</member>
    </event>
  </day>
  <day>
    <name>2</name>
    <event>
      <name>3</name>
      <member>A</member>
      <member>B</member>
    </event>
  </day>
</member>
<member>
  <name>C</name>
  <day>
    <name>1</name>
    <event>
      <name>2</name>
      <member>C</member>
    </event>
  </day>
  <day>
    <name>2</name>
    <event>
      <name>4</name>
      <member>C</member>
    </event>
  </day>
  <day>
    <name>3</name>
    <event>
      <name>5</name>
      <member>C</member>
    </event>
  </day>
</member>

為此,我嘗試了以下XQuery:

我嘗試了什么

for $member in distinct-values(//member)
return
<member>
  <name>{$member}</name>
    {for $day in //day where $day/event/member = $member
      let $event := $day/event where $event/member = $member
    return 
      <day>
        {$day/name}
        {$event}
    </day>}
</member>

但是,這不適用於過濾。 所以我為他們不是其成員的成員保留所有活動:

我得到了什么

<member>
  <name>A</name>
  <day>
    <name>1</name>
    <event>
      <name>1</name>
      <member>A</member>
      <member>B</member>
    </event>
    <event>
      <name>2</name>
      <member>C</member>
    </event>
  </day>
  <day>
    <name>2</name>
    <event>
      <name>3</name>
      <member>A</member>
      <member>B</member>
    </event>
    <event>
      <name>4</name>
      <member>C</member>
    </event>
  </day>
</member>
<member>
  <name>B</name>
  <day>
    <name>1</name>
    <event>
      <name>1</name>
      <member>A</member>
      <member>B</member>
    </event>
    <event>
      <name>2</name>
      <member>C</member>
    </event>
  </day>
  <day>
    <name>2</name>
    <event>
      <name>3</name>
      <member>A</member>
      <member>B</member>
    </event>
    <event>
      <name>4</name>
      <member>C</member>
    </event>
  </day>
</member>
<member>
  <name>C</name>
  <day>
    <name>1</name>
    <event>
      <name>1</name>
      <member>A</member>
      <member>B</member>
    </event>
    <event>
      <name>2</name>
      <member>C</member>
    </event>
  </day>
  <day>
    <name>2</name>
    <event>
      <name>3</name>
      <member>A</member>
      <member>B</member>
    </event>
    <event>
      <name>4</name>
      <member>C</member>
    </event>
  </day>
  <day>
    <name>3</name>
    <event>
      <name>5</name>
      <member>C</member>
    </event>
  </day>
</member>

當然,這應該很容易,不是嗎?

這是一個非常小的問題。 您希望過濾事件,並將$events定義$events $day的所有事件的序列。 然后,你使用= -operator進行過濾,它設置了語義 - 如果左側的任何項目(當天所有事件的成員)等於右側的任何項目(當前$member ), where子句評估為true

循環遍歷事件。

for $member in distinct-values(//member)
return
<member>
  <name>{$member}</name>
    {for $day in //day where $day/event/member = $member
      (: for instead of let :)
      for $event in $day/event where $event/member = $member
    return 
      <day>
        {$day/name}
        {$event}
    </day>}
</member>

使用謂詞而不是where子句通常會導致代碼更容易閱讀,而嵌套顯式循環也更少。 這是一個清理過的例子:

for $member in distinct-values(//member)
return
  <member>{
    <name>{ $member }</name>,
    for $day in //day[event/member = $member]
    return 
      <day>{
        $day/name,
        $day/event[member = $member]
      }</day>
  }</member>

以下是使用group by兩次的替代解決方案,僅掃描源數據一次:

for $member in //member
group by $name := $member/text()
order by $name
return <member>{
    <name>{$name}</name>,
    for $event in $member/..
    group by $day := $event/../name
    order by $day
    return <day>{
        <name>{$day}</name>,
        $event
    }</day>
}</member>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM