包含维基数据上的子查询的SPARQL查询会产生意外结果

时间:2018-04-28 13:23:30

标签: sparql wikidata blazegraph

我知道针对Wikidata SPARQL Endpoint查询的以下SPARQL是毫无意义的。在我的应用程序中自动生成类似的查询。请忽略概念上的稳健性,让我们深入研究这种奇怪的事情(至少对我而言)。

SELECT ?year1 ?year_labelTemp
    WHERE
      { 
        ?year1  <http://www.w3.org/2000/01/rdf-schema#label>  ?year_labelTemp .
        { SELECT distinct ?year1
          WHERE
            { ?film  <http://www.wikidata.org/prop/direct/P577>  ?date ;
                     <http://www.wikidata.org/prop/direct/P31>  <http://www.wikidata.org/entity/Q11424>
              BIND(year(?date) AS ?year1)
            }
        }   
      }
    limit 10

根据SPARQL中的查询评估,首先评估子查询,然后将其结果投影到包含查询。因此,将首先评估此子查询。

SELECT distinct ?year1
      WHERE
        { ?film  <http://www.wikidata.org/prop/direct/P577>  ?date ;
                 <http://www.wikidata.org/prop/direct/P31>  <http://www.wikidata.org/entity/Q11424>
          BIND(year(?date) AS ?year1)
        }

子查询给出了预期的结果(130个不同年份)。然后,该子查询(?year1变量)的结果将被投影出来并与外部选择中的三重模式结合。

?year1  <http://www.w3.org/2000/01/rdf-schema#label>  ?year_labelTemp .

但是,由于外部选择不应包含任何数据(?year1没有标签),因此连接不会产生任何结果。

令人惊讶的是(至少对我而言),首先执行的整个查询()会给出结果,结果很奇怪。

 wd:Q43576  Mië
 wd:Q221    Masèdonia
 wd:Q221    Республикэу Македоние
 wd:Q221    Republiek van Masedonië
 wd:Q212    Украина
 wd:Q212    Ukraina
 wd:Q212    Украинэ
 wd:Q212    Oekraïne
 wd:Q207    George W. Bush
 wd:Q207    George W. Bush

我错过了什么?

2 个答案:

答案 0 :(得分:2)

问题是有时候BIND没有正确地投射变量。

您可以使用以下查询进行检查:

SELECT ?year1 ?year_labelTemp ?projected
    WHERE
      { 
        ?year1  rdfs:label  ?year_labelTemp .
        hint:Prior hint:runLast true .
        { SELECT DISTINCT ?year1
          WHERE
            { ?film  wdt:P577  ?date ;
                     wdt:P31 wd:Q11424
              BIND(year(?date) AS ?year1)
              hint:SubQuery hint:runOnce true 
            }
         } 
        BIND(bound(?year1) AS ?projected)
      }
    LIMIT 10

Try it!

幸运的是,以下技巧有助于:

SELECT ?year1 ?year_labelTemp
    WHERE
      { 
        ?year1  rdfs:label  ?year_labelTemp  .
        hint:Prior hint:runLast true .
        { SELECT DISTINCT ?year1
          WHERE
            { ?film  wdt:P577  ?date ;
                     wdt:P31 wd:Q11424
              BIND(year(?date) AS ?year1)
              FILTER (?year1 > 0)
            }
         } 
      }
    LIMIT 10

Try it!

可以在没有嵌套子查询和hint:Query hint:optimizer "None"的情况下重现该错误,因此它不应该是查询优化器错误。但是用wd:Q11424替换wd:Q24862后的错误disappears很有意思。

BLZG-963似乎是最相关的问题(正如您所看到的,内置函数也是如此)。

答案 1 :(得分:0)

您写道子查询给出了确切的预期结果,但我认为您错过了一个值!有些电影的出版价值未知,例如Q18844655(至少在我写时才这样)。正是这个空值导致发现了看似随机的对象。

如果通过添加例如FILTER(datatype(?date) = xsd:dateTime).来更改内部SELECT,则只会得到实际日期,因此也只会得到实际年份,这意味着比没有过滤器时少一个值。 Try it here!

(当使用此更正后的内部SELECT时,整个过程就会超时。标签确实不喜欢像这样的奇数值。)