我正在使用实现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>
当然,这应该很容易,不是吗?
答案 0 :(得分:3)
这是一个非常小的问题。您想要过滤事件,并将$events
定义为$day
的所有事件的序列。然后,您使用设置了语义的=
- 运算符进行过滤 - 如果左侧的任何项目(当天所有事件的成员)等于右侧的任何项目side(当前$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>
答案 1 :(得分:1)
以下是使用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>