1

年にグループ化して数えるクエリがあります。いくつかの年では、カウントする項目がなく、結果が得られません。そのような年については、SPARQL がカウント 0 を返すようにしたいと考えています。

私はウィキデータ クエリ サービスhttps://query.wikidata.orgを使用しています。現在の解決策は、一連の値と実際のクエリとの結合を作成することです。私には少しぎこちなく見えます。より良い方法はありますか?

#defaultView:BarChart
select ?year ?number_of_pages ?work_label where {
  {
    select ?year (sample(?pages) as ?number_of_pages) ?work_label       
    where {
      {
        select * where {
          values (?year ?pages ?work_label) {
            ("2000" "0"^^xsd:integer "_") 
            ("2001" "0"^^xsd:integer "_") 
            ("2002" "0"^^xsd:integer "_") 
            ("2003" "0"^^xsd:integer "_") 
            ("2004" "0"^^xsd:integer "_") 
            ("2005" "0"^^xsd:integer "_") 
            ("2006" "0"^^xsd:integer "_") 
            ("2007" "0"^^xsd:integer "_") 
            ("2008" "0"^^xsd:integer "_") 
            ("2009" "0"^^xsd:integer "_") 
            ("2010" "0"^^xsd:integer "_") 
            ("2011" "0"^^xsd:integer "_")
            ("2012" "0"^^xsd:integer "_")
            ("2013" "0"^^xsd:integer "_")
            ("2014" "0"^^xsd:integer "_")
            ("2015" "0"^^xsd:integer "_")
            ("2016" "0"^^xsd:integer "_")
          }
        }
      }
      union {
        ?work wdt:P50 wd:Q18921408 .
        ?work wdt:P1104 ?pages .
        ?work wdt:P577 ?date . 
        ?work rdfs:label ?long_work_label . filter(lang(?long_work_label) = 'en')
        bind(substr(?long_work_label, 1, 20) as ?work_label)
        bind(str(year(?date)) as ?year) 
      }
    } 
    group by ?year ?work ?work_label
    order by ?year 
  }
}
4

1 に答える 1

5

ネストされたクエリはそれほど多くは必要ありません。これが簡単な解決策です:

#defaultView:BarChart
select ?year ?pages ?label       
where {
  # iterating over years
  values ?year {
    "2000" "2001" "2002" "2003" "2004" "2005" 
    "2006" "2007" "2008" "2009" "2010" "2011" 
    "2012" "2013" "2014" "2015" "2016" 
  }

  # binding defaults
  bind( 0  as ?default_pages)
  bind("_" as ?default_label)

  # if there is a work in the given year, ?work_pages and ?work_label will be bound
  optional {
    ?work wdt:P50 wd:Q18921408;
          wdt:P1104 ?work_pages;
          wdt:P577  ?work_date. 
    bind(str(year(?work_date)) as ?year).

    ?work rdfs:label ?long_work_label. 
    filter(lang(?long_work_label) = 'en').
    bind(substr(?long_work_label, 1, 20) as ?work_label)
  }

  # either take ?work_pages/label value or default and bind it as the result ?pages/label
  bind(coalesce(?work_pages, ?default_pages) as ?pages)
  bind(coalesce(?work_label, ?default_label) as ?label)
} 
order by ?year

結果のスクリーンショットは次のとおりです。

ここに画像の説明を入力


ここでのポイントはoptional+ bind/の組み合わせですcoalesce。一般的なパターンは

bind(... as ?default_foo)

optional { 
  # try to get value ?foo
}

bind(coalesce(?foo, ?default_foo) as ?result_foo)

coalesce可能な最初の値を返します (つまり、エラーなしでバインド/評価されます)。したがって、取得しようとした値がoptional { ... }バインドされていない場合は、デフォルトの値が取得され、結果としてバインドされます。それを書くためのより冗長な方法:

bind(if(bound(?foo), ?foo, ?default_foo) as ?result_foo)

ただし、coalesce複数の値を渡すことができるため、より優れています。より複雑なクエリでは、これが役立ちます。この例を参照してください。

于 2016-11-09T02:35:39.557 に答える