2

I want to query the neighbours to a country with SPARQL from Wikidata like this:

SELECT ?country ?countryLabel WHERE { 
  ?country wdt:P47 wd:Q183 . 
  FILTER NOT EXISTS{ ?country wdt:P576 ?date } # don't count dissolved country - at least filters German Democratic Republic
  SERVICE wikibase:label {
        bd:serviceParam wikibase:language "en" .
    }
}

My issue is that e.g. in this example for neighbours of germany there are still countries shown which does not exist anymore like:

  • Kingdom of Denmark or
  • Saarland.

Already tried

I could already reduce the number by the FILTER statement.

Question

  • How to make the statement to reduce it to 9 countries?
  • (also dividing in land boarder and sea boarder would be great)

Alternative

Stanislav Kralin
  • 11,070
  • 4
  • 35
  • 58
timguy
  • 2,063
  • 2
  • 21
  • 40
  • @stanislav-kralin thanks for your answer but I don't understandt why you deleted your post? Could you restore it? Your reply SPARQL was really helpful and I just wanted to reply with a further question. My question was how to filter the result on only real country borders. Because now I have also EuropeanUnion borders in my result set. Also a hint in how to find this propertiy would be helpful as I was also interested how you came to know that there is a property land and maritime boarder for border (wd:Q133346). I don't see these here: https://www.wikidata.org/wiki/Q133346 – timguy Sep 11 '18 at 08:01
  • Yes, there are problems with European Union borders with this approach. – Stanislav Kralin Sep 11 '18 at 08:07
  • It seems that `wd:Q12413618` gives better results. As to maritime and land borders, visit e. g. https://www.wikidata.org/wiki/Q3088686. They are rather additional types, not properties. In general, there is no "right" way. All of them are (partial) workarounds for data quality problems. – Stanislav Kralin Sep 11 '18 at 08:21

1 Answers1

2

You could check entities of type wd:Q133346 ('border') or wd:Q12413618 ('international border'):

SELECT ?border ?borderLabel ?country1Label ?country2Label ?isLandBorder ?isMaritimeBorder ?constraint {
  VALUES (?country1) {(wd:Q183)}
  ?border wdt:P31 wd:Q12413618 ;
          wdt:P17 ?country1 , ?country2 .
  FILTER (?country1 != ?country2)
  BIND (EXISTS {?border wdt:P31 wd:Q15104814} AS ?isLandBorder)
  BIND (EXISTS {?border wdt:P31 wd:Q3089219} AS ?isMaritimeBorder)
  BIND ((?isLandBorder || ?isMaritimeBorder) AS ?constraint)
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
  } ORDER BY ?country1Label

Try it!

In some sense, records are duplicated: for the Afghanistan–Uzbekistan border, the list contains both (?country1=Afganistan,?country2=Uzbekistan) and (?country1=Uzbekistan,?country2=Afganistan).


  • a database or lists or prepared HashMaps whatever with all countries of the world with neighbours

You could ask on https://opendata.stackexchange.com.

Stanislav Kralin
  • 11,070
  • 4
  • 35
  • 58
  • Thanks, just for completeness to filter for one country for others if they come across - add `?country1 wdt:P17 wd:Q159` to filter for a specific country. (Well easy but only thing I could contribute here ;-) ) – timguy Sep 11 '18 at 19:39
  • 1
    @timguy, you could use [`VALUES`](https://www.w3.org/TR/sparql11-query/#inline-data) instead: see update. – Stanislav Kralin Sep 11 '18 at 19:51