2013-06-18 161 views
1

我对SPARQL非常陌生,也对现有的各种语法标准感到困惑。 我奋力用下面的查询来从DBpedia中唯一的数据:DBpedia SPARQL查询返回多条记录和重复记录

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 

SPARQL results

因为任何人都可以看到,重复在结果Geffrye_MuseumInstitute_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

有一个[最近的问题(http://stackoverflow.com/q/17129225/1281433)有关如何避免因,例如,多个'FOAF出现重复的结果:名称被定义为可能对你有用。 –

+0

此外,作为创建最小工作示例的注释,如果您向查询中添加了'VALUES?Museum {dbpedia:Geffrye_Museum}',它会将'?Museum'的值限制为'dbpedia:Geffrye_Museum',因此只有重复的结果被显示。 –

回答

3

让我们先看一个案例。在葛弗莱的情况下,重复的结果发生,因为多个经度存在于数据,如下面的查询演示:

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 results

产生

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 

SPARQL results

当然,通过?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 results

采取这种方法,所有变量的产生是这样的:

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 results

这似乎有点尴尬不得不使用聚合projecti在所有的变量上,但它会工作。但是,您也可以先在子查询中进行聚合,然后以子查询为代价来清理变量投影。 (子查询不一定会对查询产生负面影响,实际上它可能恰恰相反,但查询本身有点难以阅读。)

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 results

最后,因为你需要在标准化名称以及地理坐标,最终的查询将会像下面这样。在你的问题中,你只是说你想保留“第一结果”,但没有特别的结果强制性规定,所以没有唯一的“第一结果”。有了这些数据,你可以使用(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 results

+1

你真棒! –