Wikidataで都道府県知事・市区村長を検索するためのSPARQL

Wikidataに登録されている都道府県知事や市区町村長の情報を検索するためのSPARQLのご紹介です。

※以下で紹介するSPARQLは、https://query.wikidata.org/ を使って入力することを想定しています。
※データモデルを修正したので、クエリとその説明を更新しました。

## 都道府県知事を調べる基本のSPARQL

「都道府県知事(Q1623534)」で指定されている人を引っ張ってくるクエリです。一番基本的なクエリと言えますが、残念ながらどの都道府県の知事かは出てきません。

```sparql
SELECT ?person ?personLabel WHERE {
  ?person wdt:P39 wd:Q1623534. ##都道府県知事
  SERVICE wikibase:label {
     bd:serviceParam wikibase:language "[AUTO_LANGUAGE],ja,en".
  }
}
```

## 特定の都道府県知事に紐ついた知事を調べるSPARQL

「都道府県知事(Q1623534)」ではなく、「東京都知事(Q11525354)」「北海道知事(Q33134383)」を使って指定されている場合もあります。この場合に対応するため、いったんスーパークラスを経由して検索するクエリです。

```sparql
SELECT ?person ?personLabel ?role ?roleLabel WHERE {
  ?person wdt:P39 ?role.
  ?role wdt:P279 wd:Q1623534. ##都道府県知事
  SERVICE wikibase:label {
     bd:serviceParam wikibase:language "[AUTO_LANGUAGE],ja,en".
  }
}
```

「東京都知事」などは、「上位クラス(P279)」プロパティで「都道府県知事(Q1623534)」と紐ついているのを利用しています。

## 都道府県順にソート

知事には都道府県名がついていますが、都道府県の項目を適切に取得するためには、知事の項目に対して「管轄・適用区域 (P1001)」プロパティの値を取得します。

```sparql
SELECT ?person ?personLabel ?role ?roleLabel ?prefLabel WHERE {
  ?person wdt:P39 ?role.
  ?role wdt:P279 wd:Q1623534. ##都道府県知事
  ?role wdt:P1001 ?pref.
  SERVICE wikibase:label {
     bd:serviceParam wikibase:language "[AUTO_LANGUAGE],ja,en".
  }
}
```

都道府県が分かれば都道府県順にソートしたくなりますが、そのためには更に別の項目が必要になります。ここではISO 3166-2順にソートすることにして、「ISO 3166-2コード(P300)」プロパティの値を使ってみます。

```sparql
SELECT ?person ?personLabel ?role ?roleLabel ?iso3166 WHERE {
  ?person wdt:P39 ?role. ##各都道府県知事
  ?role wdt:P1001 ?pref.
  ?pref wdt:P300 ?iso3166.
  ?role wdt:P279 wd:Q1623534. ##都道府県知事

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

これで都道府県順にソートされます。

## 基本のSPARQLその2:修飾子(qualifier)

ところで、都道府県を表示すると、同じ都道府県の知事が複数表示されているのに気づいたかもしれません。これは、歴代の都道府県知事が表示されているためです。

直近の都道府県知事のみを得るには、都道府県知事を止めた「終了日」が入力されていない項目のみを選ぶようにします。そのためには修飾子(qualifier)を使います。
修飾子とは、プロパティと値のペアにさらにプロパティ＆値をつっつけて、より情報を与えるためのものです。

修飾子として「終了日(P582)」を使い、終了日が存在していない項目を一覧するクエリは以下になります。

```sparql
SELECT ?person ?personLabel ?role ?roleLabel ?iso3166 WHERE {
  ?person p:P39 ?st.
  ?st ps:P39 ?role.
  ?role wdt:P279 wd:Q1623534. ##都道府県知事
  ?role wdt:P1001 ?pref.
  ?pref wdt:P300 ?iso3166.
  FILTER NOT EXISTS { ?st pq:P582 ?enddate }

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

修飾子は、「p」「ps」「pq」という3つのprefixを組み合わせて使います。

また、絞り込みにはFILTERを使っています。`FILTER NOT EXISTS {...}`で、ブレース内の条件が適用されない項目だけが得られます。

## 市区町村長を調べるSPARQL

市区町村長についても調べてみます。

市区町村については、「首長(Q30185)」を使っているものがあるようです。が、「首長(Q30185)」は日本以外でも使われているため、海外の情報がたくさん引っかかってしまいます。そこで日本のみを抽出してみましょう。

```sparql
SELECT ?person ?personLabel ?city ?cityLabel WHERE {
  ?person p:P39 ?st.
  ?st ps:P39 wd:Q30185. ## 首長
  {
  ?st pq:P642 ?city.
  ?city wdt:P17 wd:Q17.
  } UNION {
  ?st pq:P1001 ?city.
  ?city wdt:P17 wd:Q17.
  }
  SERVICE wikibase:label {
     bd:serviceParam wikibase:language "[AUTO_LANGUAGE],ja,en".
  }
}
```

ここでも先ほどと同様、「以下についての(P642)」と「管轄・適用区域(P1001)」とをUNIONでマージしています。
また、P17(country, 国)を使って日本に限定しています。

```sparql
SELECT ?person ?personLabel ?city ?cityLabel WHERE {
  ?person p:P39 ?st.
  ?st ps:P39 wd:Q30185. ## 首長
  ?st pq:P642 ?city.
  ?city wdt:P17 wd:Q17.
  SERVICE wikibase:label {
     bd:serviceParam wikibase:language "[AUTO_LANGUAGE],ja,en".
  }
}
```

しかし、ここでも問題があります。「首長(Q30185)」ではなく、「（日本の）市長(Q19961107)」をプロパティとして使っていていたり、また「京都市長(Q27826875)」を使っていたり場合があるのです。こちらに対応したのが以下のクエリです。

```sparql
SELECT ?person ?personLabel ?city ?cityLabel ?mayorLabel WHERE {
  ?person p:P39 ?st.
  {
    ?st ps:P39 wd:Q30185. ## 首長
    {
      ?st pq:P642 ?city.
      ?city wdt:P17 wd:Q17.
    } UNION {
      ?st pq:P1001 ?city.
      ?city wdt:P17 wd:Q17.
    }
  } UNION {
    ?st ps:P39 ?mayor.
    ?mayor wdt:P279 wd:Q30185. ## 首長
    ?mayor wdt:P17 wd:Q17.
    {
      ?st pq:P1001 ?city.
    } UNION {
      ?st pq:P642 ?city.
    } UNION {
      ?mayor wdt:P1001 ?city.
    }
  }
  SERVICE wikibase:label {
     bd:serviceParam wikibase:language "[AUTO_LANGUAGE],ja,en".
  }
}
```

二重にUNIONを使っている（しかも２箇所も）ので、だいぶすごいことになっていますが、これでいけそうです。

とはいえ、これは京都市だけが特別なようなので、京都市を変えた方が早いような気がしますね……。どのようなデータモデル・スキーマ（？）で情報を蓄積していくのかは、今後の大きな課題かと思います。