SPARQL / CONSTRUCT中的条件绑定

时间:2017-02-25 20:22:10

标签: sparql

我有一个SPARQL CONSTRUCT,其工作原理如下:

CONSTRUCT {
  ?uri rdfs:label ?label; 
       foo:has-value ?v.        
}
WHERE {
  ?uri 
     rdfs:label ?label; 
     foo:has-flag ?f.

  BIND ( IF ( ?f = 0, "Value for Zero", IF ( ?f = 1, "Value for One", '' ) ) AS ?v )
}

问题是当?f既不是0也不是1(但仍然有一些值)时,我根本不需要has-value语句。使用上面的语法,我得到?uri has-value ''。它可以工作,如果我可以为?v分配某种“null”,或者避免绑定,但我在规范中找不到类似的东西。

任何解决方案?

编辑solution by Scott适用于常见的基于图形的查询。我来自的案例涉及使用VALUES is more complicated,到目前为止我找不到解决方案。

编辑/ 2 :安迪在耶拿邮件列表中建议的error-triggering solution工作正常!当我们想跳过原始值时,另一种我觉得更具可读性的方法是binding an unbound variable

2 个答案:

答案 0 :(得分:3)

根据评论中的反馈,这是一个基于OPTIONAL的解决方案,应该符合所有标准:

CONSTRUCT {
  ?uri rdfs:label ?label; 
       foo:has-value ?v.        
}
WHERE {
  ?uri rdfs:label ?label .     
  ?uri foo:has-flag ?f.
  OPTIONAL { FILTER (?f = 0)
      BIND("Value for Zero" AS ?v)
  }
  OPTIONAL { FILTER (?f = 1)
      BIND("Value for One" AS ?v)
  }
}

正如所指出的,此前的解决方案不会涵盖有标签的情况,但?f不是0或1:

CONSTRUCT {
  ?uri rdfs:label ?label; 
       foo:has-value ?v.        
}
WHERE {
  ?uri 
     rdfs:label ?label; 
     foo:has-flag ?f. 
  FILTER (?f = 0 || ?f = 1)
  BIND ( IF ( ?f = 0, "Value for Zero", IF ( ?f = 1, "Value for One", '' ) ) AS ?v )
}

答案 1 :(得分:1)

有点hacky但是应该使用创建一个空白节点,然后过滤掉那些:

CONSTRUCT {
  ?uri rdfs:label ?label; 
       foo:has-value ?v.        
}
WHERE {
  ?uri rdfs:label ?label .
  OPTIONAL { 
    ?uri foo:has-flag ?f.

    BIND ( IF ( ?f = 0, "Value for Zero", 
             IF ( ?f = 1, "Value for One", BNODE() ) 
         ) AS ?v )
    FILTER(!ISBLANK(?v))
  }
}