如何“旋转”SPARQL导致“循环”?

问题描述 投票:1回答:1

问题

我想为答案的每个元素选择大小为n的任意子集。

对于一个特定元素,如莱比锡市,我可以在DBpedia(http://www.dbpedia.org/sparql)中解决这个问题:

查询单个元素的示例

select ?p
{
 ?p dbo:birthPlace dbr:Leipzig.
} limit 3

输出单个元素

http://dbpedia.org/resource/Walter_Ulbricht
http://dbpedia.org/resource/Anita_Berber
http://dbpedia.org/resource/Martin_Benno_Schmidt

但我希望旋转输出并为所有(或一定数量)城市执行此操作:

期望输出多个元素

City         Person1               Person2                 Person3
dbr:Leipzig  dbr:Walter_Ulbricht       dbr:Anita_Berber    dbr:Martin_Benno_Schmidt
dbr:Bonn     dbr:Anton_Schumacher      dbr:Hermann_Wallich dbr:Fritz_Simrock
dbr:Paris    dbr:Adrien-Marie_Legendre dbr:André_Malraux   dbr:Anselme_Payen
...

我尝试使用以下查询解决此问题:

SELECT ?city SAMPLE(?p1) SAMPLE(?p2) SAMPLE(?p3)
{
 ?city ^dbo:birthPlace ?p1,?p2,?p3.
 ?city a dbo:City.

 FILTER(?p1<?p2&&?p2<?p3) # prevent permutations and duplicates

} GROUP BY ?city # only one line per city
LIMIT 10 

但是我不确定这是否是最好的解决方案,我有几个问题:

  • 使用更大的n这种编写查询的方式变得很麻烦,是否有更优雅的选项(例如使用子查询)?
  • 这个查询是否给了我想要的所有结果,即它是否对整行进行采样,还是通过单独对每个变量进行采样然后跳过有效的解决方案而失去结果?
  • 如果它确实返回了我通过重复单个元素查询得到的所有结果,它是否具有相同的效率,还是在过滤掉之前运行了大量的排列?如果不是,有没有办法更有效地写它?
sparql
1个回答
2
投票

这是一个相当优雅和有效的解决方案:

  1. 在子查询中,将GROUP BYgroup_concat聚合一起使用,将一个城市的所有人的URI合并为一个长字符串。
  2. 在子查询之外,使用字符串函数来拆分长字符串并获取前n个项目。

在这里完成前100个城市,每个城市有5个人:

SELECT ?c ?p1 ?p2 ?p3 ?p4 ?p5 {
    {
        SELECT ?c (group_concat(?p; separator=' ') AS ?list1) {
            {
                SELECT ?c { ?c a dbo:City } LIMIT 100
            }
            OPTIONAL { ?p dbo:birthPlace ?c }
        }
        GROUP BY ?c
    }
    BIND (if(?list1, strAfter(?list1, ' '), undef) AS ?list2)
    BIND (if(?list2, strAfter(?list2, ' '), undef) AS ?list3)
    BIND (if(?list3, strAfter(?list3, ' '), undef) AS ?list4)
    BIND (if(?list4, strAfter(?list4, ' '), undef) AS ?list5)

    BIND (if(?list1, if(contains(?list1, ' '), IRI(strBefore(?list1, ' ')), IRI(?list1)), undef) AS ?p1)
    BIND (if(?list2, if(contains(?list2, ' '), IRI(strBefore(?list2, ' ')), IRI(?list2)), undef) AS ?p2)
    BIND (if(?list3, if(contains(?list3, ' '), IRI(strBefore(?list3, ' ')), IRI(?list3)), undef) AS ?p3)
    BIND (if(?list4, if(contains(?list4, ' '), IRI(strBefore(?list4, ' ')), IRI(?list4)), undef) AS ?p4)
    BIND (if(?list5, if(contains(?list5, ' '), IRI(strBefore(?list5, ' ')), IRI(?list5)), undef) AS ?p5)
}
© www.soinside.com 2019 - 2024. All rights reserved.