首页 > 解决方案 > 如何使用 SPARQL "MINUS" 作为 SQL "NOT IN" 等同于获取所有只在一个团队中打球的玩家

问题描述

我正在对 Lahman 棒球数据库中的数据进行 sparql 查询。这里有一些示例数据来展示我的查询需要做什么。

@prefix ma: <http://mydataset.com/ns/master#> .
ma:billybo01 ma:nameFirst "Billy" .
ma:billybo01 ma:nameLast "Bored" .
ma:chrisgow01 ma:nameFirst "Chris" .
ma:chrisgow01 ma:nameLast "Gowan" .
ma:bradlee01 ma:nameFirst "Brad" .
ma:bradlee01 ma:nameLast "Lee" .


@prefix teamQ2: <http://mydataset.com/ns/teamQ2#> .
@prefix yearQ2: <http://mydataset.com/ns/yearQ2#> .
@prefix ma: <http://mydataset.com/ns/master#> .
teamQ2:BS1 yearQ2:1871 ma:billybo01 .
teamQ2:BS1 yearQ2:1872 ma:billybo01 .
teamQ2:BS1 yearQ2:1873 ma:billybo01 .
teamQ2:LAN yearQ2:1874 ma:billybo01 .

teamQ2:LAN yearQ2:1871 ma:chrisgow01 .
teamQ2:LAN yearQ2:1872 ma:chrisgow01 .

teamQ2:BS1 yearQ2:1871 ma:bradlee01 .
teamQ2:BS1 yearQ2:1872 ma:bradlee01 .

我正在尝试获取只为 LAN 团队而不是其他团队效力的所有球员的名字和姓氏。我的尝试是我在下面展示的。我希望查询任何一年在团队 LAN 中的所有玩家,获取他们的 masterID,然后从该集合中减去曾经出现在 LAN 以外的团队中的所有玩家。然后我只需将 masterId 与最后的名字和姓氏相匹配。现在它正在返回数据,就好像MINUSFILTER !EXISTS相互抵消一样,它只返回所有在局域网上玩的玩家。MINUS除了或之外,我还需要使用其他东西FILTER !EXISTS吗?

PREFIX ma: <http://mydataset.com/ns/master#>
PREFIX teamQ2: <http://mydataset.com/ns/teamQ2#> 
SELECT DISTINCT ?nameFirst ?nameLast
WHERE
{
  teamQ2:LAN ?yearID ?masterID .
  MINUS{FILTER (
      !EXISTS {
          teamQ2:LAN ?yearID ?nonLANmasterID .
      }
      )}
  ?masterID ma:nameLast ?nameLast .
  ?masterID ma:nameFirst ?nameFirst .
}
ORDER BY ?nameLast ?nameFirst

标签: sparqlrdf

解决方案


建模是一个相当不寻常的,但这里是基于您的描述的查询大纲:

  1. 找出所有的teamQ2:LAN ?p ?o .三元组。

  2. 拒绝任何与属性-对象对(FILTER NOT EXISTS)不同的主题的匹配。(FILTER(?otherteam != teamQ2:LAN )?p ?o

    (这实际上是“在同一年没有为同一支球队效力,因为?pis yearQ2:1871etc 包括了这一年。)

前缀马:
前缀团队Q2:  
选择 *
在哪里
{
  teamQ2:LAN ?p ?masterID 。
  过滤器不存在 {
      ?otherteam?p?masterID。
      过滤器(?其他团队!= teamQ2:LAN)
  }
  ?masterID ma:nameLast ?nameLast 。
  ?masterID ma:nameFirst ?nameFirst 。
}

在这种情况下,也可以这样做:

  1. 查找teamQ2:LAN.
  2. 查找不属于teamQ2:LAN.
  3. MINUS?masterID以上两点。
前缀马:
前缀团队Q2:  
选择 *
在哪里
{
  teamQ2:LAN ?yearID ?masterID 。
  减 {
      ?otherteam?yearID?masterID。
      过滤器(?其他团队!= teamQ2:LAN)
  }
  ?masterID ma:nameLast ?nameLast 。
  ?masterID ma:nameFirst ?nameFirst 。
}

我认为您应该考虑将数据及时记录为事件:

在“年”或三人组中“为球队效力”的球员:

ma:bradlee01 :playedForInYear [ :team teamQ2:BS1 ; : 1871 年]。
ma:bradlee01 :playedForInYear [ :team teamQ2:BS1 ; : 1872 年]。

推荐阅读