【问题标题】:Aggregating results from SPARQL query聚合 SPARQL 查询的结果
【发布时间】:2013-08-13 15:05:23
【问题描述】:

我正在查询推文数据集:

SELECT * WHERE {
  ?tweet smo:tweeted_at ?date ;
         smo:has_hashtag ?hashtag ;
         smo:tweeted_by ?account ;
         smo:english_tweet true .
  FILTER ( ?date >= "20130722"^^xsd:date && ?date < "20130723"^^xsd:date )
}

如果一条推文有多个主题标签,则每个主题标签的结果集中只有一行。我有什么办法可以将标签聚合到一个数组中吗?

【问题讨论】:

    标签: sparql


    【解决方案1】:

    您可以通过标识推文的变量GROUP BY,然后使用GROUP_CONCAT 将主题标签连接成类似数组的东西,但它仍然是一个字符串,之后您需要对其进行解析。例如,给定的数据像

    @prefix smo: <http://example.org/> .
    @prefix : <http://example.org/> .
    
    :tweet1 smo:tweeted_at "1" ;
            smo:has_hashtag "tag1", "tag2", "tag3" ;
            smo:tweeted_by "user1" ;
            smo:english_tweet true .
    
    :tweet2 smo:tweeted_at "2" ;
            smo:has_hashtag "tag2", "tag3", "tag4" ;
            smo:tweeted_by "user2" ;
            smo:english_tweet true .
    

    你可以使用类似的查询

    prefix smo: <http://example.org/>
    
    select ?tweet ?date ?account (group_concat(?hashtag) as ?hashtags) where {
      ?tweet smo:tweeted_at ?date ;
             smo:has_hashtag ?hashtag ;
             smo:tweeted_by ?account ;
             smo:english_tweet true .
    }
    group by ?tweet ?date ?account
    

    得到如下结果:

    --------------------------------------------------
    | tweet      | date | account | hashtags         |
    ==================================================
    | smo:tweet2 | "2"  | "user2" | "tag4 tag3 tag2" |
    | smo:tweet1 | "1"  | "user1" | "tag3 tag2 tag1" |
    --------------------------------------------------
    

    您可以指定组连接中使用的分隔符,因此如果有一些字符不能出现在主题标签中,您可以将其用作分隔符。例如,假设| 不能出现在主题标签中,您可以使用:

    (group_concat(?hashtag;separator="|") as ?hashtags)
    

    反而得到

    --------------------------------------------------
    | tweet      | date | account | hashtags         |
    ==================================================
    | smo:tweet2 | "2"  | "user2" | "tag4|tag3|tag2" |
    | smo:tweet1 | "1"  | "user1" | "tag3|tag2|tag1" |
    --------------------------------------------------
    

    如果您使用的语言具有一些文字数组语法,您甚至可以复制它:

    (concat('[',group_concat(?hashtag;separator=","),']') as ?hashtags)
    
    ----------------------------------------------------
    | tweet      | date | account | hashtags           |
    ====================================================
    | smo:tweet2 | "2"  | "user2" | "[tag4,tag3,tag2]" |
    | smo:tweet1 | "1"  | "user1" | "[tag3,tag2,tag1]" |
    ----------------------------------------------------
    

    现在,它不会影响此处的数据,但如果数据中存在重复项,group_concat 实际上会在连接中包含重复项。例如,从以下(为了示例,我只是用values 提供数据):

    prefix : <http://example.org/>
    
    select ?tweet (concat('[',group_concat(?hashtag;separator=','),']') as ?hashtags)
    where {
      values (?tweet ?hashtag) { 
        (:tweet1 "tag1") (:tweet1 "tag1") (:tweet1 "tag2") (:tweet1 "tag3")
        (:tweet2 "tag2") (:tweet2 "tag3") (:tweet2 "tag4")
      }
    }
    group by ?tweet
    

    我们得到包含[tag1,tag1,tag2,tag3]的结果,即包含?hashtag的重复值:

    -------------------------------------
    | tweet   | hashtags                |
    =====================================
    | :tweet2 | "[tag2,tag3,tag4]"      |
    | :tweet1 | "[tag1,tag1,tag2,tag3]" |
    -------------------------------------
    

    我们可以通过使用group_concat(distinct ?hashtag;...)来避免这种情况:

    prefix : <http://example.org/>
    
    select ?tweet (concat('[',group_concat(distinct ?hashtag;separator=','),']') as ?hashtags)
    where {
      values (?tweet ?hashtag) { 
        (:tweet1 "tag1") (:tweet1 "tag1") (:tweet1 "tag2") (:tweet1 "tag3")
        (:tweet2 "tag2") (:tweet2 "tag3") (:tweet2 "tag4")
      }
    }
    group by ?tweet
    
    --------------------------------
    | tweet   | hashtags           |
    ================================
    | :tweet2 | "[tag2,tag3,tag4]" |
    | :tweet1 | "[tag1,tag2,tag3]" |
    --------------------------------
    

    【讨论】:

    • 作为此处给出的GROUP_CONCAT 解决方案的替代方案,您还可以使用SAMPLE 聚合 - 它不是连接所有值,而是选择一个值。
    • 如果有多个属性具有多个要分组的值,请确保在 group_concat 中使用DISTINCTgroup_concat(DISTINCT ?hashtag)
    • @prathamesh 原始问题的过滤器不起作用,因为日期文字不合法。即使是,您也必须检查特定端点是否支持日期排序。
    • @prathamesh 所有功能都在可在线免费获得的标准中指定。在这种情况下,year 被指定为接受日期时间,而不是日期。
    • @JoshuaTaylor 感谢您的详细解释!!
    猜你喜欢
    • 1970-01-01
    • 2014-10-22
    • 2018-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多