【问题标题】:SPARQL query including a subquery on Wikidata gives unexpected resultsSPARQL 查询(包括 Wikidata 上的子查询)给出了意想不到的结果
【发布时间】:2018-04-28 13:23:29
【问题描述】:

我知道针对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

我错过了什么?

【问题讨论】:

  • 这就是人们所说的 Blazegraph 后端中的 bug
  • 将本地提取部署到 graphdb 时也会出现同样的问题!

标签: sparql wikidata blazegraph


【解决方案1】:

问题是有时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,尝试将其投影到外部查询,然后尝试仅添加一个三元组模式以获取投影的变量类型
  • SELECT ?year1 ?x ?y WHERE { { SELECT ?year1 WHERE { BIND (2 as ?year1) } } optional {?x ?y ?year1 .} } LIMIT 1
  • 一个有趣的事实:当我使用 GraphDB 作为我的后端时,更改语句的顺序会改变结果。如果子查询在外部查询中声明,然后是三元组模式,使用您建议的技巧 (FILTER ?year1 > 0),它会按预期工作,使用其他可能的顺序将我们带回到第 1 格。
  • 在此期间我会做更多的测试。
  • @MedianHilal,从语义上讲,这或多或少是相同的。似乎在投影 XPath 函数结果时可能会出现问题,如在 BLZG-963 中。这个问题相当复杂,但嵌套子查询并不是重现所必需的。
【解决方案2】:

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

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

(当使用这个更正的内部 SELECT 时,整个事情都会超时。标签似乎真的不喜欢像这样的奇数值。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-03
    相关资源
    最近更新 更多