我们先来看一个案例。在 Geffrye 的情况下,会出现重复的结果,因为数据中存在多个经度,如以下查询所示:
SELECT ?museum ?latitude ?longitude
WHERE {
VALUES ?museum { dbpedia:Geffrye_Museum }
?museum a dbpedia-owl:Museum ;
geo:lat ?latitude ;
geo:long ?longitude .
}
GROUP BY ?museum ?latitude ?longitude
SPARQL 结果
产生
museum latitude longitude
http://dbpedia.org/resource/Geffrye_Museum 51.5317 -0.07663
http://dbpedia.org/resource/Geffrye_Museum 51.5317 -0.0762194
幸运的是,这很容易补救。正如在这个问题中所讨论的,您可以按其特征值对结果进行分组,然后对这些值进行采样、最小化、最大化等,以获得您想要的结果。例如,如果您想要最大的经度值,您可以MAX(?longtude) as ?longitude
在 SELECT 中使用,如下面的查询,它产生一个值。
SELECT ?museum ?latitude (MAX(?longitude) as ?longitude)
WHERE {
VALUES ?museum { dbpedia:Geffrye_Museum }
?museum a dbpedia-owl:Museum ;
geo:lat ?latitude ;
geo:long ?longitude .
}
GROUP BY ?museum ?latitude
SPARQL 结果
当然,它需要一些知识来分组?latitude
和最大化?longitude
。?museum
将其他值分组并使用聚合投影来提取其他值可能是一个更好的主意,如下所示:
SELECT ?museum (MAX(?latitude) as ?latitude) (MAX(?longitude) as ?longitude)
WHERE {
VALUES ?museum { dbpedia:Geffrye_Museum }
?museum a dbpedia-owl:Museum ;
geo:lat ?latitude ;
geo:long ?longitude .
}
GROUP BY ?museum
SPARQL 结果
对所有变量采用这种方法会产生如下结果:
SELECT DISTINCT ?Museum
(SAMPLE(?name) as ?name)
(SAMPLE(?abstract) as ?abstract)
(SAMPLE(?thumbnail) as ?thumbnail)
(MAX(?latitude) as ?latitude)
(MAX(?longitude) as ?longitude)
(SAMPLE(?photoCollection) as ?photoCollection)
(SAMPLE(?website) as ?website)
(SAMPLE(?homepage) as ?homepage)
(SAMPLE(?wikilink) as ?wikilink)
WHERE {
?Museum a dbpedia-owl:Museum ;
dbpprop:name ?name ;
dbpedia-owl:abstract ?abstract ;
dbpedia-owl:thumbnail ?thumbnail ;
geo:lat ?latitude ;
geo:long ?longitude ;
dbpprop:hasPhotoCollection ?photoCollection ;
dbpprop:website ?website ;
foaf:homepage ?homepage ;
foaf:isPrimaryTopicOf ?wikilink .
FILTER(langMatches(lang(?abstract),"EN"))
FILTER (langMatches(lang(?name),"EN"))
}
GROUP BY ?Museum
LIMIT 20
SPARQL 结果
必须对所有变量使用聚合投影似乎有点尴尬,但它会起作用。但是,您也可以先在子查询中进行聚合,这将清理变量投影,但代价是子查询。(子查询不一定对查询产生负面影响;实际上可能正好相反。不过,查询本身有点难以阅读。)
SELECT * WHERE {
# Select museums and a single latitude and longitude for them.
{
SELECT ?Museum (MAX(?longitude) as ?longitude) (MAX(?latitude) as ?latitude) WHERE {
?Museum a dbpedia-owl:Museum ;
geo:lat ?latitude ;
geo:long ?longitude .
}
GROUP BY ?Museum
}
# Get the rest of the properties of the museum.
?Museum dbpprop:name ?name ;
dbpedia-owl:abstract ?abstract ;
dbpedia-owl:thumbnail ?thumbnail ;
dbpprop:hasPhotoCollection ?photoCollection ;
dbpprop:website ?website ;
foaf:homepage ?homepage ;
foaf:isPrimaryTopicOf ?wikilink .
FILTER(langMatches(lang(?abstract),"EN"))
FILTER (langMatches(lang(?name),"EN"))
}
GROUP BY ?Museum
LIMIT 20
SPARQL 结果
最后,由于您需要对名称和地理坐标进行规范化,您的最终查询将类似于以下内容。在您的问题中,您只说要保留“第一个结果”,但没有对结果施加特定的顺序,因此没有唯一的“第一个结果”。有了手头的数据,您可以使用(MIN(?name) as ?name)
并获得您想要的博物馆研究所名称,但如果您有特定的限制,您需要弄清楚如何使其更具体。
SELECT * WHERE {
# Select museums and a single latitude, longitude, and name for them.
{
SELECT ?Museum
(MIN(?name) as ?name)
(MAX(?longitude) as ?longitude)
(MAX(?latitude) as ?latitude)
WHERE {
?Museum a dbpedia-owl:Museum ;
dbpprop:name ?name ;
geo:lat ?latitude ;
geo:long ?longitude .
FILTER (langMatches(lang(?name),"EN"))
}
GROUP BY ?Museum
}
# Get the rest of the properties of the museum.
?Museum dbpprop:name ?name ;
dbpedia-owl:abstract ?abstract ;
dbpedia-owl:thumbnail ?thumbnail ;
dbpprop:hasPhotoCollection ?photoCollection ;
dbpprop:website ?website ;
foaf:homepage ?homepage ;
foaf:isPrimaryTopicOf ?wikilink .
FILTER(langMatches(lang(?abstract),"EN"))
}
LIMIT 20
SPARQL 结果