我对SPARQL很陌生,并且也因为它存在的多种语法标准而感到困惑。 我正在努力使用以下查询从DBpedia获取唯一数据:
SELECT DISTINCT ?Museum, ?name, ?abstract, ?thumbnail, ?latitude,
?longitude, ?photoCollection, ?website, ?homepage, ?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"))
}
LIMIT 20
任何人都可以看到,Geffrye_Museum
和Institute_for_Museum_Research
的条目会在结果中重复,因为Institute_for_Museum_Research
的名称有两个不同的值,Geffrye_Museum
有两个经度值。在这两个重复的情况下,我希望丢弃第二个值;即,对于Geffrye_Museum
,必须忽略经度值-0.0762194
,对于Institute_for_Museum_Research
,必须忽略名称值"Institut für Museumsforschung"@en
。
请注意,我已经对我想要的字段应用了过滤,这只是DBpedia中我想要在查询级别处理的大量数据。那么,当同一列有多个值时,如何让DBpedia仅返回第一个值?
答案 0 :(得分:4)
让我们先来看一个案例。对于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
产生
museum latitude longitude
http://dbpedia.org/resource/Geffrye_Museum 51.5317 -0.07663
http://dbpedia.org/resource/Geffrye_Museum 51.5317 -0.0762194
幸运的是,这很容易补救。正如this question中所讨论的,您可以按照其特征值对结果进行分组,然后对值进行采样,最小化,最大化等,以获得您想要的精确值。例如,如果您想要最有价值的经度,您可以在SELECT中使用MAX(?longtude) as ?longitude
,如下面的查询中所示,它产生一个值。
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
当然,它假定一些知识要按?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
对所有变量采用这种方法产生如下:
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
在所有变量上使用聚合投影似乎有点尴尬,但它会起作用。但是,您也可以先在子查询中进行聚合,然后以子查询为代价清理变量投影。 (子查询不一定会对查询产生负面影响;实际上它可能相反。但查询本身有点难以阅读。)
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
最后,由于您需要对名称和地理坐标进行规范化,因此您的最终查询将如下所示。在你的问题中,你只是说你想保留“第一个结果”,但结果没有特别的顺序,因此没有独特的“第一个结果”。有了手头的数据,你可以使用{{1你会得到博物馆研究所想要的名字,但如果你有一个特别的约束,你需要弄清楚如何使它更具体。
(MIN(?name) as ?name)