SPARQL 不同对
SPARQL Distinct pairs
我有一个 table,其中有相同作者的文档。我需要获取不同的文档对。我做了以下事情:
SELECT DISTINCT ?d1 ?d2 WHERE {
?d1 myns:creator ?x.
?d2 myns:creator ?y.
FILTER (?x=?y && ?d1!=?d2).
}
GROUP BY ?d1 ?d2
但是对于这个 DOC1, DOC2
和 DOC2, DOC1
都在结果中。我需要摆脱其中一对。
这是整个三元组数据库:
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix myns: <http://my.local.namespace#> .
_:doc1 rdf:type myns:Document.
_:doc1 myns:creator _:Pete.
_:doc1 myns:year "2000"^^xsd:integer.
_:doc1 myns:publisher _:p1.
_:doc2 rdf:type myns:Document.
_:doc2 myns:creator _:John.
_:doc2 myns:year "2004"^^xsd:integer.
_:doc2 myns:publisher _:p2.
_:doc3 rdf:type myns:Document.
_:doc3 myns:creator _:Pete.
_:doc3 myns:publisher _:p3.
_:doc4 rdf:type myns:Document.
_:doc4 myns:creator _:Bob.
_:doc4 myns:year "2010"^^xsd:integer.
_:doc4 myns:publisher _:p2.
_:Pete rdf:type myns:Person.
_:Pete myns:knows _:Bob.
_:Pete myns:knows _:John .
_:John rdf:type myns:Person.
_:John myns:age "29"^^xsd:integer.
_:John myns:knows _:Bob.
_:Bob rdf:type myns:Person.
_:Bob myns:age "35"^^xsd:integer.
执行查询后我得到的结果是:
D1 D2
_:891f1e98-b411-4e54-9533-18d530f09c6ddoc1 _:891f1e98-b411-4e54-9533-18d530f09c6ddoc3
_:891f1e98-b411-4e54-9533-18d530f09c6ddoc3 _:891f1e98-b411-4e54-9533-18d530f09c6ddoc1
值得注意的是,从技术上讲,这两对是相同的。我只需要一个(即其中一个就足够了)。我不确定环境特征。但是有芝麻框架
你可以用一个小技巧来做到这一点:将 !=
变成 <
(或 >
),并将值转换为字符串,这样你就可以进行词法比较:
SELECT DISTINCT ?d1 ?d2 WHERE {
?d1 myns:creator ?x.
?d2 myns:creator ?y.
FILTER (?x=?y && STR(?d1) < STR(?d2)).
}
GROUP BY ?d1 ?d2
这是基于这样的想法,即对于任何一对不相等的标识符,一个标识符总是大于另一个(按词法排序)。因此,在任何两对中,实际上只会选择一对。
更新 现在您已经显示了您的数据,我们可以看出问题是您没有使用 IRI 来区分您的文档,而是使用空白节点。上述查询不起作用,因为根据 SPARQL 标准,空白节点是无序的(因此直接通过 <
进行比较不起作用),而且 STR
函数被定义为仅对文字或IRI,不在空白节点上。
最好的解决办法是改变你的数据,并确保你使用正确的 IRIs,因为无论你是否能以某种方式使这个查询对这个数据起作用,结果几乎是无用的:空白节点没有意义在他们的本地范围之外,所以你的查询 returns 的文档标识符不能真正被重用;例如,您将无法执行 SPARQL 查询来获取文档 _:doc1
的任何属性(尽管公平起见,Sesame 在 API 中有解决此问题的方法)。
顺便说一下,将空白节点更改为 IRI 的一个非常简单的方法是将 turtle 文件中出现的所有 _:
替换为 myns:
。
这将在一些 系统中工作:
SELECT ?d1 ?d2 WHERE {
?d1 myns:creator ?x.
?d2 myns:creator ?y.
FILTER (?x=?y && STR(IRI(?d1)) < STR(IRI(?d2))).
}
?d1
和 ?d2
将成为空白节点。但是空白节点是空白的。
因此,要为 <
提供排序,我们需要某种查询范围内的标签或与每个关联的值。
您的数据没有任何可区分的三元组 person.It 最好将真实姓名放入数据中:
_:Pete rdfs:label "Pete" .
更好的是,使用 FOAF 词汇。
有些系统允许 IRI()
中的空白节点 - 从技术上讲,它是 SPARQL 规范的扩展。然后,您可以采用 STR
形式进行比较。对我有用的数据 (Apache Jena) - 你没有说你使用的是哪个 RDF 系统。
最好的解决方案是将区分信息放入数据中。
我有一个 table,其中有相同作者的文档。我需要获取不同的文档对。我做了以下事情:
SELECT DISTINCT ?d1 ?d2 WHERE {
?d1 myns:creator ?x.
?d2 myns:creator ?y.
FILTER (?x=?y && ?d1!=?d2).
}
GROUP BY ?d1 ?d2
但是对于这个 DOC1, DOC2
和 DOC2, DOC1
都在结果中。我需要摆脱其中一对。
这是整个三元组数据库:
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix myns: <http://my.local.namespace#> .
_:doc1 rdf:type myns:Document.
_:doc1 myns:creator _:Pete.
_:doc1 myns:year "2000"^^xsd:integer.
_:doc1 myns:publisher _:p1.
_:doc2 rdf:type myns:Document.
_:doc2 myns:creator _:John.
_:doc2 myns:year "2004"^^xsd:integer.
_:doc2 myns:publisher _:p2.
_:doc3 rdf:type myns:Document.
_:doc3 myns:creator _:Pete.
_:doc3 myns:publisher _:p3.
_:doc4 rdf:type myns:Document.
_:doc4 myns:creator _:Bob.
_:doc4 myns:year "2010"^^xsd:integer.
_:doc4 myns:publisher _:p2.
_:Pete rdf:type myns:Person.
_:Pete myns:knows _:Bob.
_:Pete myns:knows _:John .
_:John rdf:type myns:Person.
_:John myns:age "29"^^xsd:integer.
_:John myns:knows _:Bob.
_:Bob rdf:type myns:Person.
_:Bob myns:age "35"^^xsd:integer.
执行查询后我得到的结果是:
D1 D2
_:891f1e98-b411-4e54-9533-18d530f09c6ddoc1 _:891f1e98-b411-4e54-9533-18d530f09c6ddoc3
_:891f1e98-b411-4e54-9533-18d530f09c6ddoc3 _:891f1e98-b411-4e54-9533-18d530f09c6ddoc1
值得注意的是,从技术上讲,这两对是相同的。我只需要一个(即其中一个就足够了)。我不确定环境特征。但是有芝麻框架
你可以用一个小技巧来做到这一点:将 !=
变成 <
(或 >
),并将值转换为字符串,这样你就可以进行词法比较:
SELECT DISTINCT ?d1 ?d2 WHERE {
?d1 myns:creator ?x.
?d2 myns:creator ?y.
FILTER (?x=?y && STR(?d1) < STR(?d2)).
}
GROUP BY ?d1 ?d2
这是基于这样的想法,即对于任何一对不相等的标识符,一个标识符总是大于另一个(按词法排序)。因此,在任何两对中,实际上只会选择一对。
更新 现在您已经显示了您的数据,我们可以看出问题是您没有使用 IRI 来区分您的文档,而是使用空白节点。上述查询不起作用,因为根据 SPARQL 标准,空白节点是无序的(因此直接通过 <
进行比较不起作用),而且 STR
函数被定义为仅对文字或IRI,不在空白节点上。
最好的解决办法是改变你的数据,并确保你使用正确的 IRIs,因为无论你是否能以某种方式使这个查询对这个数据起作用,结果几乎是无用的:空白节点没有意义在他们的本地范围之外,所以你的查询 returns 的文档标识符不能真正被重用;例如,您将无法执行 SPARQL 查询来获取文档 _:doc1
的任何属性(尽管公平起见,Sesame 在 API 中有解决此问题的方法)。
顺便说一下,将空白节点更改为 IRI 的一个非常简单的方法是将 turtle 文件中出现的所有 _:
替换为 myns:
。
这将在一些 系统中工作:
SELECT ?d1 ?d2 WHERE {
?d1 myns:creator ?x.
?d2 myns:creator ?y.
FILTER (?x=?y && STR(IRI(?d1)) < STR(IRI(?d2))).
}
?d1
和 ?d2
将成为空白节点。但是空白节点是空白的。
因此,要为 <
提供排序,我们需要某种查询范围内的标签或与每个关联的值。
您的数据没有任何可区分的三元组 person.It 最好将真实姓名放入数据中:
_:Pete rdfs:label "Pete" .
更好的是,使用 FOAF 词汇。
有些系统允许 IRI()
中的空白节点 - 从技术上讲,它是 SPARQL 规范的扩展。然后,您可以采用 STR
形式进行比较。对我有用的数据 (Apache Jena) - 你没有说你使用的是哪个 RDF 系统。
最好的解决方案是将区分信息放入数据中。