【问题标题】:Why simple subtraction of two sets is not working?为什么简单的两组相减不起作用?
【发布时间】:2014-06-09 12:42:14
【问题描述】:

我有以下 xml 文件。我需要找到不在 $v 中的 $c 中的成员:

(C) - (V) = desired result


let $c := /transport/trips/trip
let $v := /transport/trips/trip
where (data($c/@vehicle)="PKR856") 
return
<result2>
        {$v/(from|to|through)/string()} 
        {$c/(from|to|through)/string()} 
</result2>

现在我要减去它们,这是我的代码:

let $c := /transport/trips/trip
let $v := /transport/trips/trip
where (data($c/@vehicle)="PKR856") 
return
<result2>
    { $c/(from|to|through)/string()[not(. = $v/(from|to|through)/string())]} 
</result2>

我试过了,这也行不通:

let $c := /transport/trips/trip/
let $v := /transport/trips/trip/(from|to|through)/string()
where (data($c/@vehicle)="PKR856") 
return
<result2>
    { $c/(from|to|through)/string()[not(. = $v)]} 
</result2>

输出:

内部错误代码,参数

编辑

这是 XML 文件:

  <trips>
  <trip driver="d2345" vehicle="PKR856" date="12-DEC-2007">
    <from>London</from>
    <to>Newcastle</to>
    <through stop="1">Leicester</through>
    <through stop="2">Nottingham</through>
    <time>1</time>
  </trip>
  <trip driver="d6767" vehicle="UUQ007" date="10-MAY-2008">
    <from>Paris</from>
    <to>Rome</to>
    <through stop="1">Lyon</through>
    <through stop="2">Milan</through>
    <time>15</time>
  </trip>
  <trip driver="d2345" vehicle="PKR856" date="14-DEC-2007">
    <from>Paris</from>
    <to>Amsterdam</to>
    <through stop="2">Brussel</through>
    <through stop="1">Mons</through>
    <time>4</time>
  </trip>
</trips>

我需要返回具体车号未到过的城市名称?

我已经尝试了这些但没有用:

let $driver-cities := /trips/trip[@vehicle="PKR856"]/(from, to, through)/string()
return /trips/trip/(from, to)/string()[not(. = $driver-cities)]

其实我把答案改成:

let $c := /transport/trips/trip/(from|to|through)/text()
let $v := /transport/trips/trip[@vehicle eq "PKR856"]/(from|to|through)/text()
return
<result>
            { $c except $v} 
</result>

【问题讨论】:

  • 您能提供一个示例文档吗?另外$c$v 是相同的,所以$c except $v 将始终为空。这与您的原始查询不同吗?
  • @LeoWörteler 我已经编辑并添加了我的 XML 文件。

标签: xml xquery xquery-sql


【解决方案1】:

您可以使用except 运算符来获得两组的差异。也许以下内容对您有用:

let $c := /transport/trips/trip
let $v := /transport/trips/trip[@vehicle eq "PKR856"] 
return

    $c except $v

虽然您的其中一个集合是所有 trip 元素的完整集合,但以下产生相同的结果,并且对我来说似乎更简单:

/transport/trips/trip[@vehicle ne "PKR856"]

与@Bernard 合作,我相信最简单的期望答案是:

let $x := /transport/trips/trip[@vehicle ne "PKR856"]/(from|to|through)/text()
return
    <result>{$x}</result>

【讨论】:

  • 感谢您的回答,但这是回程,不是由特定车辆完成的。我担心的是特定车辆未访问城市名称。
  • 这可能是我需要的,但我得到错误:$c/(from|to|through)/string() except $v/(from|to|through)/string()跨度>
  • 您会收到一个错误,因为except 在节点序列上操作,而不是在原子类型(例如字符串)序列上操作。
【解决方案2】:

XQuery 3.0 中,您可以使用group by clause 查找访问过某个城市的所有车辆。然后可以使用它来过滤特定车辆未访问过的城市的结果:

let $vehicle := 'UUQ007'
for $trip in //trip
let $curr-vehicle := $trip/@vehicle/string()
for $city in $trip/(from, through, to)/string()
group by $city
where not($curr-vehicle = $vehicle)
return $city

这将为您的示例文档返回London Newcastle Leicester Nottingham Amsterdam Brussel Mons。如果设置$vehicle := 'PKR856',则结果为Rome Lyon Milan。我在BaseX的最新版本中尝试过这个。

如果您的处理器不支持 XQuery 3.0,以下查询可能效率较低,但在 XQuery 1.0 中计算的结果相同:

let $vehicle := 'UUQ007'
for $city in distinct-values(//trip/(from, through, to))
where not(//trip[@vehicle=$vehicle]/(from, through,to) = $city)
return $city

【讨论】:

    猜你喜欢
    • 2021-08-14
    • 2019-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-25
    • 1970-01-01
    • 2012-06-25
    • 1970-01-01
    相关资源
    最近更新 更多