【问题标题】:unexpected behaviour with FILTER on xsd:date在 xsd:date 上使用 FILTER 出现意外行为
【发布时间】:2017-10-07 06:08:52
【问题描述】:

如何将结果计数(罢工发生次数)过滤到特定年份(1970 年)?我的解决方案提供了意想不到的结果。在查询中,我写下了我尝试过的替代方案及其结果。

其他人([1][2])提到的解决方案并没有解决问题。

端点是: https://api.druid.datalegend.net/datasets/rlzijdeman/ClariahTech2017/containers/clariahTech2017/sparql

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX gg: <http://www.gemeentegeschiedenis.nl/gg-schema#>
PREFIX strikes: <https://iisg.amsterdam/vocab/>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>

SELECT ?muni ?sdate (COUNT(?muni) as ?muniCount)  
WHERE {
  ?strike strikes:place ?splace .
  ?strike strikes:date ?sdate .
  ?muni rdf:type gg:Municipality .
  ?muni rdfs:label ?ggplace . 
  FILTER regex(?splace, ?ggplace)

  ### TASK: Filter results above to strikes in 1970 only

  # solution 1: extract year and FILTER on 1970
  # FILTER ( year(?sdate) = 1970 )
  ### Virtuoso 22003 Error SR586: Incomplete RDF box as argument 0 for year().

  # solution 2: filter on ?sdate
  # FILTER ( ?sdate >= '1970-01-01'^^xsd:date && ?sdate <= '1970-12-31'^^xsd:date )
  ### Virtuoso 2201B Error SR098: regexp error at '? [Arnhem ( Gelderland )]' column 0 (nothing to repeat)
  ####### Why? This was no problem under solution 1 ?!
  ####### Also: note that each of these works seperately, but not together(!):
  # FILTER ( ?sdate >= '1970-01-01'^^xsd:date )
  # FILTER ( ?sdate <= '1970-12-31'^^xsd:date )

} 
LIMIT 10

【问题讨论】:

    标签: xsd sparql virtuoso


    【解决方案1】:

    关于“解决方案1”:

    函数yearxsd:dateTime 类型的文字作为输入-您的数据仅包含xsd:datexsd:gYearMonth 文字。这就是演员阵容可能失败的原因。

    关于“解决方案2”:

    可能是 Virtuoso 中的一个错误。但总的来说,我不确定为什么在这里需要 REGEX。如果您只是想摆脱语言标签进行比较,请使用str 函数。它也更快:

    PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
    PREFIX gg: <http://www.gemeentegeschiedenis.nl/gg-schema#>
    PREFIX strikes: <https://iisg.amsterdam/vocab/>
    PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
    
    SELECT * {
      ?strike strikes:place ?splace .
      ?strike strikes:date ?sdate .
      ?muni rdf:type gg:Municipality .
      ?muni rdfs:label ?ggplace . 
      FILTER (?sdate >= '1970-01-01'^^xsd:date && ?sdate < '1971-01-01'^^xsd:date)
      FILTER(str(?splace) = str(?ggplace)) 
    } 
    LIMIT 10
    

    我在您的查询中发现的另一件事很奇怪,您不应该计算罢工而不是市政当局本身吗?我的意思是,据我了解,您想获得特定日期每个市镇的罢工次数(如果我错了,请纠正我)。如果是这样,查询应该如下所示:

    PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
    PREFIX gg: <http://www.gemeentegeschiedenis.nl/gg-schema#>
    PREFIX strikes: <https://iisg.amsterdam/vocab/>
    PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
    
    SELECT ?muni (COUNT(?strike) as ?strikes) {
      ?strike strikes:place ?splace .
      ?strike strikes:date ?sdate .
      ?muni rdf:type gg:Municipality .
      ?muni rdfs:label ?ggplace . 
      FILTER (?sdate >= '1970-01-01'^^xsd:date && ?sdate < '1971-01-01'^^xsd:date)
      FILTER(str(?splace) = str(?ggplace)) 
    } 
    GROUP BY ?muni
    LIMIT 10
    

    此外,如果有多次罢工,获取?sdate 没有意义,对吧?除非您想像这样获取所有罢工的日期:

    PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
    PREFIX gg: <http://www.gemeentegeschiedenis.nl/gg-schema#>
    PREFIX strikes: <https://iisg.amsterdam/vocab/>
    PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
    
    SELECT ?muni (COUNT(?strike) as ?strikes) (GROUP_CONCAT(?sdate; separator = ";") as ?s_dates) {
      ?strike strikes:place ?splace .
      ?strike strikes:date ?sdate .
      ?muni rdf:type gg:Municipality .
      ?muni rdfs:label ?ggplace . 
      FILTER (?sdate >= '1970-01-01'^^xsd:date && ?sdate < '1971-01-01'^^xsd:date)
      FILTER(str(?splace) = str(?ggplace)) 
    } 
    GROUP BY ?muni
    LIMIT 10
    

    小评论

    我也尝试先转换为xsd:dateTime,然后选择year

    FILTER (year(xsd:dateTime(?sdate)) = 1970)
    

    有趣的是,由于 29.2,这失败了。 :D :

    Virtuoso 22007 Error DT006: Cannot convert 1911-02-29 to datetime : Too many days (29, the month has only 28)
    

    不确定,如果 2 月的值 28 在 Virtuoso 中被硬编码,或者它是否必然是闰年 - 至少这是有道理的,因为 1911 年不是闰年(1911 年不能被 4 整除,因此,它是一个普通的年份)

    【讨论】:

    • 我知道,我不应该这样做:但非常感谢您:您的回答很完整,它帮助我理解的不仅仅是这个问题。
    • 可能是 Virtuoso 中的一个错误。 — 我认为原因是当 REGEX(?splace, ?ggplace) 被评估为 REGEX("Arnhem (Gelderland)", "Arnhem (Gelderland)") 或类似的东西时,括号不会被转义。此外,@Richard 似乎使用了REGEX,因为strikes:place 的值有时不等于市政标签。可能他可以使用STRSTARTS,但是当然,这应该是端点维护者的问题,将strikes:place的值而不是字符串,而不是强迫用户执行这些模糊连接......
    • 问题是为什么没有日期过滤器查询不会失败。即使删除 LIMIT 并将超时设置为 0 也不会导致此异常。
    • PREFIX rdf: &lt;http://www.w3.org/1999/02/22-rdf-syntax-ns#&gt; PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt; PREFIX gg: &lt;http://www.gemeentegeschiedenis.nl/gg-schema#&gt; PREFIX strikes: &lt;https://iisg.amsterdam/vocab/&gt; PREFIX xsd: &lt;http://www.w3.org/2001/XMLSchema#&gt; SELECT distinct ?muni ?splace { ?strike strikes:place ?splace . ?muni rdf:type gg:Municipality . ?muni rdfs:label ?ggplace . FILTER (strstarts(str(?splace), str(?ggplace))) FILTER (str(?splace) != str(?ggplace)) } limit 10
    • 说明子串匹配会导致错误的结果。
    猜你喜欢
    • 2019-11-03
    • 2019-09-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-02
    • 1970-01-01
    • 2021-10-02
    • 2011-05-08
    • 1970-01-01
    相关资源
    最近更新 更多