我有以下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 .
}
如果?name
和?includedName
有多个值,如何返回单个名称。我会很高兴第一个,或者最少数量的角色来选择保留。
这是柏拉图影响Bertrand Russell的另一个例子。我想这会返回一行,但我得到四行:
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 .
}
答案 0 :(得分: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
如果您只对名称感兴趣而不关心选择实际资源,那么最外面的?philosopher
中不需要?influence
和SELECT
,并且可以将其设为< / p>
SELECT ?pName (SAMPLE(?iName) as ?iName)
WHERE { …
您还可能希望在结尾添加ORDER BY
,以便更轻松地检查结果:
…
GROUP BY ?philosopher ?pName ?influence
ORDER BY ?pName
对于柏拉图来说,最后的结果包括以下几行:
"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
任意选择哲学家的foaf:name
之一,但aggregate algebra中还有其他函数您可以用来选择一个值。如果您想按顺序使用“第一个”值,Min可能会对您感兴趣。
这实际上与SPARQL规范的Section 12, Subqueries中的子查询的示例非常相似。在该示例中,以下查询用于选择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
}
}
这不是很难适应哲学影响问题。哲学家的问题始于选择所有的哲学家及其名字,按实际的哲学家资源分组,并使用样本为每个哲学家挑选一个代表性名称。外部查询也是如此,但不是选择哲学家,而是选择影响每个哲学家的实体。将结果分组并选择影响力的代表名称。
答案 1 :(得分:1)
我已经确定了如何为哲学家选择唯一的名称,请参阅下面的sparql,它为每个哲学家返回一个名称。
但是,我没有看到为什么要将这个结合到更大的查询中,该查询为哲学家和受影响的哲学家返回一个名称而不为每个哲学家运行一次这将是一个庞大而笨拙的查询。我的感觉是,如果我分别运行哲学名称和查询影响并在代码中查找名称而不是sparql,我的代码将更具可读性。也许我错过了一些sparql功能,这将使这很容易。请建议
以下是我如何获得唯一名称的说明:
从foaf获取哲学家的所有名称:names和dbprop:names 过滤以仅包含至少包含一个拉丁字母字符的名称(A-Z) 找到最短名称的长度 选择所有最短的名称
中的最小值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