跳到内容

SPARQL/子查询

来自维基教科书,开放的书籍,用于开放的世界

SPARQL 允许将一个 SELECT 查询嵌套在另一个查询中。内部 SELECT 查询称为 *子查询*,并首先进行评估。子查询结果变量随后可以在外部 SELECT 查询中使用。

最简单的示例

SELECT ?x ?y WHERE {
  VALUES ?x { 1 2 3 4 }
  {
    SELECT ?y WHERE { VALUES ?y { 5 6 7 8 }  }
  }  # \subQuery
} # \mainQuery

试试看!

以下示例计算世界每个国家的人口,并将人口表示为世界总人口的百分比。为了计算世界总人口,它使用了一个子查询。

SELECT ?countryLabel ?population (round(?population/?worldpopulation*1000)/10 AS ?percentage)
WHERE {
  ?country wdt:P31 wd:Q3624078;    # is a sovereign state
           wdt:P1082 ?population.

  { 
    # subquery to determine ?worldpopulation
    SELECT (sum(?population) AS ?worldpopulation)
    WHERE { 
      ?country wdt:P31 wd:Q3624078;    # is a sovereign state
               wdt:P1082 ?population. 
    }
  }

  SERVICE wikibase:label {bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en".}
}
ORDER BY desc(?population)

试试看!

包含子查询的查询的语法如下所示。子查询基本上与简单查询相同,并用 { 大括号 } 包围。

SELECT  ... query result variables ...
WHERE 
{
        ... query pattern ...

        { # subquery
          SELECT  ... subquery result variables ...
          WHERE 
          {
                  ... subquery pattern ...
          }
                  ... optional subquery modifiers ...
        } # end of subquery

}
        ... optional query modifiers ...

子查询通常可以与 LIMIT 一起使用,通过将任务分割来避免查询超时。例如,此查询超时 

#100 humans with exactly 6 months between their month of birthday and their month of death.
SELECT DISTINCT ?itemLabel ?item WHERE {
  ?item wdt:P31 wd:Q5 ;
        p:P569/psv:P569 [wikibase:timePrecision ?datePrecision1; wikibase:timeValue ?naissance] ;
        p:P570/psv:P570 [wikibase:timePrecision ?datePrecision2; wikibase:timeValue ?mort ].
  filter(?datePrecision1>10)
  filter(?datePrecision2>10)
  
  bind(month(?mort) - month(?naissance) as ?mois)
  bind(day(?mort) - day(?naissance) as ?jour)
  
  filter(abs(?mois) = 6)
  filter(?jour = 0)

  SERVICE wikibase:label {bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en".}
}
ORDER BY ?itemLabel
LIMIT 100

试试看!

但将 limit 设置在子查询中选定项目的限制上,并将标签服务放在子查询之外的相同查询没有超时 

#100 humans with exactly 6 months between their month of birthday and their month of death.
SELECT DISTINCT ?itemLabel ?item WHERE {
  {
    SELECT DISTINCT ?item WHERE {
      ?item wdt:P31 wd:Q5 ; 
            p:P569/psv:P569 [wikibase:timePrecision ?datePrecision1; wikibase:timeValue ?naissance] ;
            p:P570/psv:P570 [wikibase:timePrecision ?datePrecision2; wikibase:timeValue ?mort ].

      filter(?datePrecision1>10)
      filter(?datePrecision2>10)

      bind(month(?mort) - month(?naissance) as ?mois)
      bind(day(?mort) - day(?naissance) as ?jour)
      filter(abs(?mois) = 6)
      filter(?jour = 0)
    }
    LIMIT 100
  }

  SERVICE wikibase:label {bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en".}
}
ORDER BY ?itemLabel

试试看!


华夏公益教科书