可以简化此SPARQL查询吗?

时间:2017-11-28 00:02:10

标签: sparql rdf graph-databases

目前我正在为LDBC Benchmark实施SPARQL查询。我提出了bi-read-3查询的解决方案。数据模式的相关部分如下: enter image description here

查询说明:

  

查找给定年份的给定月份内的消息中使用的标记以及下个月使用的标记。对于这两个月,计算使用每个标记的消息计数。

我的解决方案(with some syntax highlight):

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX sn: <http://www.ldbc.eu/ldbc_socialnet/1.0/data/>
PREFIX snvoc: <http://www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/>
PREFIX sntag: <http://www.ldbc.eu/ldbc_socialnet/1.0/tag/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dbpedia: <http://dbpedia.org/resource/>
PREFIX dbpedia-owl: <http://dbpedia.org/ontology/>


SELECT ?tagName (SUM(?countMonth1) as ?countMonth1) (SUM(?countMonth2) as ?countMonth2) (ABS( SUM(?countMonth1) - SUM(?countMonth2) ) as ?diff)
WHERE
{ 
  {
    SELECT ?tagName (COUNT(?message) as ?innerCountMonth1)
    WHERE {

      BIND ( 2010 as ?year1 ) .
      BIND ( 9 as ?month1 ) .

      {
        ?message rdf:type snvoc:Comment 
      } UNION {
        ?message rdf:type snvoc:Post 
      } .
      ?message snvoc:creationDate ?creationDate .
      FILTER ((year(?creationDate) = ?year1 && month(?creationDate) = ?month1) )

      ?message snvoc:hasTag ?tag .
      ?tag foaf:name ?tagName .

    }
    GROUP BY ?tagName
  } UNION {
    SELECT ?tagName (COUNT(?message) as ?innerCountMonth2)
    WHERE {

      BIND ( 2010 as ?year1 ) .
      BIND ( 9 as ?month1 ) .
      BIND ( ?year1 + FLOOR(?month1 / 12.0) as ?year2 ) .
      BIND ( IF (?month1 = 12, 1, ?month1 + 1) as ?month2 ) .
      {
        ?message rdf:type snvoc:Comment 
      } UNION {
        ?message rdf:type snvoc:Post 
      } .
      ?message snvoc:creationDate ?creationDate .
      FILTER (year(?creationDate) = ?year2 && month(?creationDate) = ?month2 ) 

      ?message snvoc:hasTag ?tag .
      ?tag foaf:name ?tagName .

    }
    GROUP BY  ?tagName
  }

  BIND ( COALESCE(?innerCountMonth1, 0) as ?countMonth1 )
  BIND ( COALESCE(?innerCountMonth2, 0) as ?countMonth2 )
}
GROUP BY ?tagName
ORDER BY DESC(?diff) ?tagName

我觉得有一个更简单的解决方案,但我无法理解。

我的问题是:这个查询可以用更简单/更有效的方式实现吗?例如:没有嵌套查询或只是更快的方式。

我是SPARQL的新手,所以我会感谢每一个有用的评论或改进。

1 个答案:

答案 0 :(得分:1)

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX snvoc: <http://www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>

SELECT
?tagName
(SUM(xsd:integer(?isFirst)) AS ?countMonth1)
(SUM(xsd:integer(?isSecond)) AS ?countMonth2)
(ABS(?countMonth1 - ?countMonth2) AS ?diff) 
WHERE
  {
  VALUES (?year1 ?month1) {(2010 9)}
  VALUES (?type) {(snvoc:Comment) (snvoc:Post)}
  ?message a ?type; snvoc:hasTag/foaf:name ?tagName; snvoc:creationDate ?creationDate .
  BIND (year(?creationDate) AS ?year) .
  BIND (month(?creationDate) AS ?month) .
  BIND (IF (?month1 = 12, ?year1 + 1, ?year1     ) AS ?year2) .
  BIND (IF (?month1 = 12,          1, ?month1 + 1) AS ?month2) .
  BIND (((?month1 = ?month) && (?year1 = ?year)) AS ?isFirst) .
  BIND (((?month2 = ?month) && (?year2 = ?year)) AS ?isSecond) .
  FILTER (?isFirst || ?isSecond)
  }
  GROUP BY ?tagName HAVING (bound(?tagName))

<强>更新

见评论。