2

我有以下 DBpedia SPARQL,显示了影响哲学家的哲学家。但是,当哲学家有多个 时,它会返回重复项foaf:name

SELECT ?name ?influencedName
  WHERE {
  ?philosopher a dbpedia-owl:Philosopher ;
    dbpedia-owl:influenced ?influenced ;
    foaf:name ?name .
  ?influenced  a dbpedia-owl:Philosopher ;
    foaf:name ?influencedName .
}

SPARQL 结果

?name如果and有多个值,如何返回单个名称?includedName。我会很高兴第一个,或者选择要保留的最少字符数。

这是柏拉图影响伯特兰·罗素的另一个例子。我希望这个返回一行,但我得到四个:

SELECT ?name ?influencedName
  WHERE {
  ?philosopher a dbpedia-owl:Philosopher ;
    dbpedia-owl:influenced ?influenced ;
    foaf:name ?name , "Plato"@en .
  ?influenced  a dbpedia-owl:Philosopher ;
    foaf:name ?influencedName, "Bertrand Arthur William Russell, 3rd Earl Russell"@en .
}

SPARQL 结果

4

2 回答 2

3

查询

听起来您想要一个类似的查询:

SELECT ?philosopher ?pName ?influence (SAMPLE(?iName) as ?iName)
WHERE {
  # This subquery selects all the philosophers and
  # selects just one of their names . 
  {
    SELECT ?philosopher (SAMPLE(?pName) as ?pName) WHERE {
      ?philosopher a dbpedia-owl:Philosopher ;
                   foaf:name ?pName .
    }
    GROUP BY ?philosopher
  }

  # This main query selects the influence of the 
  # philosophers and select their names.  The GROUP
  # BY on the outer query puts all the
  # (?philosopher,?pName,?influence,?iName) tuples 
  # that have the same ?philosopher, ?pName, and 
  # influence together, and the (SAMPLE(?iName) as ?iName)
  # in the outer SELECT combines them all, choosing an 
  # arbitrary representative ?iName.
  ?influence dbpedia-owl:influenced ?philosopher ;
             a dbpedia-owl:Philosopher ;
             foaf:name ?iName .
}
GROUP BY ?philosopher ?pName ?influence

SPARQL 结果

如果你只对名称感兴趣,而不关心选择实际资源,你不需要?philosopher?influence在最外层SELECT,可以做到

SELECT ?pName (SAMPLE(?iName) as ?iName)
WHERE { …

SPARQL 结果

您可能还想ORDER BY在最后添加一个以使结果更容易检查:

…
GROUP BY ?philosopher ?pName ?influence
ORDER BY ?pName

SPARQL 结果

对于柏拉图来说,这些最后的结果包括以下行:

"Plato"@en  "Socrates"@en
"Plato"@en  "Parmenides"@en
"Plato"@en  "Zeno of Elea"@en
"Plato"@en  "Pythagoras"@en
"Plato"@en  "Gorgias"@en
"Plato"@en  "Protagoras"@en
"Plato"@en  "Heraclitus"@en

在我在这里编写的查询中,我曾经任意SAMPLE选择一个哲学家的s,但是聚合代数foaf:name中还有其他函数可以用来选择一个值。 如果您希望按顺序排列“第一个”值,您可能会对Min感兴趣。

子查询、GROUP BY 和 SAMPLE、MIN 等。

这实际上与第 12 节SPARQL 规范的子查询中给出的子查询示例非常相似。在该示例中,以下查询用于选择 Alice 认识的人,并且对于每个人,只选择一个人的姓名:

PREFIX : <http://people.example/>
SELECT ?y ?minName
WHERE {
  :alice :knows ?y .
  {
    SELECT ?y (MIN(?name) AS ?minName)
    WHERE {
      ?y :name ?name .
    } GROUP BY ?y
  }
}

这不难适应哲学影响问题。哲学家问题首先选择所有哲学家及其姓名,按实际哲学家资源分组,并使用样本为每个哲学家选择一个代表姓名。外部查询也是如此,但不是选择哲学家,而是选择影响每个哲学家的实体。将结果分组并选择影响的代表名称。

于 2013-06-16T01:23:34.050 回答
1

我已经确定了如何为哲学家选择唯一名称,请参阅下面的 sparql,它为每个哲学家返回一个名称。

但是,我不明白为什么要将此合并到更大的查询中,该查询为哲学家和受影响的哲学家返回一个名称,而无需为每个哲学家运行一次此代码,这将是一个庞大且笨拙的查询。我的感觉是,如果我分别运行哲学家名称和受查询影响的名称,并在代码中而不是 sparql 中查找名称,我的代码将更具可读性。也许我错过了一些 sparql 功能,这将使这变得容易。请指教

以下是我如何获得唯一名称的描述:

从 foaf:names 和 dbprop:names 获取 Philosopher 的所有名称 过滤以仅包含至少包含一个拉丁字母字符 (AZ) 的名称 查找最短名称的长度 选择所有最短名称中的最小值

PREFIX dbpedia: <http://dbpedia.org/>
PREFIX dbpedia-owl: <http://dbpedia.org/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dbpprop: <http://dbpedia.org/property/>

SELECT ?philosopher (min(?name) as ?minName)
WHERE {{
   ?philosopher foaf:name ?name        .
  } UNION {
   ?philosopher dbpprop:name ?name     .
  }
  FILTER( strlen(?name) = ?minLength )   .  # get the shortest names
  FILTER( REGEX( str(?name) , "[A-Z]" )) .  # exlude names with no latin charachters
  {
    SELECT ?philosopher (min(strlen(?name)) as ?minLength)
    WHERE {{
      ?philosopher a  dbpedia-owl:Philosopher ;
         foaf:name ?name .
    } UNION {
      ?philosopher a  dbpedia-owl:Philosopher ;
         dbpprop:name ?name .
    }
    FILTER( REGEX( str(?name) , "[A-Z]" )) .
    }
    GROUP BY ?philosopher
  }
}
GROUP BY ?philosopher
ORDER BY ?philosopher
于 2013-06-16T16:52:31.157 回答