On wikidata SPARQL get coordinates in degree? - sparql

I want to get coordinates via SPARQL from wikidata displayed as degrees (e.g. 54°54'36"N). It is displayed in wikidata like this, so I suspect there is a built-in function for this purpose but I can not find it.
Example query:
SELECT DISTINCT ?countryLabel ?long
{
?country wdt:P31 wd:Q6256 ;
p:P1332 [ psv:P1332 [wikibase:geoLatitude ?long ]].
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
}
This gives the longitude as number (e.g. -30.08). I can calculate the desired output format from this result but would prefer to get it directly from the query.
Thanks.

Related

Unexpected missing value from Wikidata query

I'm using the Wikidata query service to learn the SPARQL query language. I'm trying to get information on countries and their identifying information.
Here is a simple query which is intended to return a list of countries (https://www.wikidata.org/wiki/Q6256) along with their ISO 3-letter codes (https://www.wikidata.org/wiki/Property:P298):
SELECT ?country ?countryLabel ?iso
WHERE
{
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
?country wdt:P31 wd:Q6256; # wd:Q6256="country; wd:Q3624078="sovereign state"
wdt:P298 ?iso.
}
ORDER BY ?countryLabel
I notice that at least one country is consistently missing from the results, Georgia, and I'm confused about why.
According to its wikidata page:
It is an instance of country (wd:Q6256)
It does have an ISO-3166 3-letter country code (wdt:P298)
I've tried various transformations of this query (e.g. don't include the ISO codes, use labels in different languages, etc) and I consistently get the same result: Georgia is missing.
However if I switch from (instance of a country wd:Q6256) to (instance of a sovereign state wd:Q3624078; a subclass of wd:Q6256), then Georgia is included in the results.
I am at a loss to explain this result; the entity in question should be an instance of both "country" and "sovereign state." And clearly it works for most of the other countries of the world, whose data is represented similarly in Wikidata, in that they're listed as instances of both country wd:Q6256 and sovereign state wd:Q3624078.
Can anyone explain what aspect of the SPARQL language, or representation of the data in question, that I'm not understanding here?
The claim for instanceOf Sovereign State has a PreferredRank, so it's selected in preference to all the other claims which have a NormalRank. Also, SPARQL doesn't do inheritance by default unless you explicitly bake it into the query (because it can be expensive), so you don't automatically get Sovereign State just because it's a subclass of Country.
This will include Georgia
SELECT ?country ?countryLabel ?iso
WHERE
{
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
?country p:P31/ps:P31 wd:Q6256; # wd:Q6256="country; wd:Q3624078="sovereign state"
wdt:P298 ?iso.
}
ORDER BY ?countryLabel
but note that it includes deprecated claims as well. I cribbed it from this set of examples: https://en.wikibooks.org/wiki/SPARQL/WIKIDATA_Qualifiers,_References_and_Ranks
As mentioned by #horcrux in the comments, you can modify this to exclude deprecated claims by using a FILTER expression:
SELECT ?country ?countryLabel ?iso
WHERE
{
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
FILTER(?rank != wikibase:DeprecatedRank) . ?country p:P31 [ ps:P31 wd:Q6256 ; wikibase:rank ?rank ] ;
wdt:P298 ?iso.
}
ORDER BY ?countryLabel
The results are the same in this case, but it's something worth thinking about when you're considering what kind of data you're looking for.

How to search a list of Wikidata IDs and return the P31 ("instance of") property using SPARQL?

How do I get the instance type(s) (i.e., property=P31 and associated labels) for multiple Wikidata IDs in a single query? Ideally, I want to output a list with the columns: Wikidata ID | P31 ID | P31 Label, with multiple rows used if a Wikidata ID has more than one P31 attached.
I am using the web query service, which works well in part, but I am struggling to understand the syntax. I have so far managed to work out how to process a list of items, and return each one as a row (simple I know!), but I can't work out how to generate a new column that gives the P31 item:
SELECT ?item
WHERE {
VALUES ?item { wd:Q1347065 wd:Q731635 wd:Q105492052 }
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
I have found the following from a previusly answered question here, which returns multiple rows per an item of interest, but this requires specifying the P31 type at the outset, which is what I am looking to generate.
Any help would be appreciated as I am really stuck understanding the syntax.
Update:
I have now worked out how to return P31s for a single ID. I need to expand this query to receive a list of IDs, and include the ID as a column:
SELECT ?item ?itemLabel
WHERE
{
wd:Q18656 wdt:P31 ?item.
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
If I correctly understood your problem, you can use the following query:
SELECT ?item ?class ?classLabel
WHERE {
VALUES ?item { wd:Q1347065 wd:Q731635 wd:Q105492052 }
?item wdt:P31 ?class .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
Here, first you fix the possible values for ?item, then you say that ?item is instance of a certain ?class and contestually you also retrieve the label for such ?class.

Return "instances of" property for a wikidata item using SPARQL

I have a list of wikidata items I wish to extract the "instance of" property from. For example, looking up Q1339 I can see that it has a single instance type (P:31) labelled "human" (Q5). I have tried to write a simple query that would extract that but I am not getting any records returned. I am v. new to SPARQL so it's very likely I'm missing something obvious.
SELECT ?item ?itemLabel
WHERE
{
?item wdt:P31 wd:Q1339.
SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}

Get information from Wikidata

I have this Wikidata query that returns all the football stadiums with the names, coordinates, club labels and stuff like this. But I cannot figure out how to also get the country and city names where stadiums are located (and possibly the coordinates of the cities too).
Here is my query:
SELECT ?club ?clubLabel ?venue ?venueLabel ?coordinates
WHERE
{
?club wdt:P31 wd:Q476028 .
?club wdt:P115 ?venue .
?venue wdt:P625 ?coordinates .
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
}
Link to test the query
EDIT 19th november 2020:
I need the timezone of the cities so I tried this query after looking at the documentation but it does not return the value. Just links like "wd:Q6723" :
SELECT DISTINCT ?timezone ?club ?locationLabel ?countryLabel ?clubLabel ?venue ?venueLabel ?coordinates
WHERE
{
?venue (wdt:P421|wd:Q12143) ?timezone .
?club wdt:P31 wd:Q476028 .
?club wdt:P115 ?venue .
?venue wdt:P625 ?coordinates .
OPTIONAL {?club wdt:P159|(wdt:P115/(wdt:P131|wdt:P276)) ?location .
OPTIONAL { ?location wdt:P17 ?country . }
}
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
} limit 500
Split over two now. Original query:
SELECT DISTINCT ?club ?locationLabel ?countryLabel ?clubLabel ?venue
?venueLabel ?coordinates
WHERE {
?club wdt:P31 wd:Q476028 .
?club wdt:P115 ?venue .
?venue wdt:P625 ?coordinates .
OPTIONAL {
?club wdt:P159|(wdt:P115/(wdt:P131|wdt:P276)) ?location .
OPTIONAL { ?location wdt:P17 ?country . }
}
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
} limit 500
(Update #2: Previously, I asked for the club's timezone. But, of course, that's not the sort of data usually recorded for a club. Instead, you have to go via the location/venue/headquarters or similar, and possibly a level up to region/country because some suburb also doesn't have timezone data.
This is the general idea how it should work, but it's running into a timeout, and so am I:
SELECT DISTINCT ?timezone ?timezoneLabel ?offset
?club ?clubLabel
WHERE {
?club wdt:P31 wd:Q476028 .
# via country. not perfect, because some have multiple timezones, but shoud be faster
?club wdt:P17/wdt:P421 ?timezone .
# what I really want to do; all sorts of alternatives
#?club wdt:P115?/(wdt:P159|wdt:P276)/wdt:P131?/wdt:P421 ?timezone .
?timezone wdt:P2907 ?offset.
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
} limit 500
Short explanation:
This uses three new things. OPTIONAL makes the following statement, well, optional. Clubs where nothing can be found will still be included in the output. The second OPTIONAL ist nested in the first, as it's pointless to ask for the country of a location that we haven't found.
The pipe symbol (|) allows for alternatives. Here, I'm asking for "headquarter location (P159) or check for two different ways to specify the location of the stadium. The slash, used in the latter case, denotes a path (club / venue / "located in district|location").
If there is missing data (there will be missing data), you may want to look at examples and figure out if there are other common patterns that locations are recorded. You could, for example, move the inner OPTIONAL outside for cases where the club has a country statement but no other, more specific, location.
Update: I've included the timezone as requested in the comment. To note:
?timezoneLabel gets the timezone's label (= name), just as ?clubLabel gets the club's. The apppended "...Label" is a "magic" function that translates from IDs to huma-readable labels. It is enabled by including that SERVICE wikibase:label... line.
As you might want to use these timezones, I've included the marked line that gets the numeric offset in hours.
The offset may vary because UTC doesn't have dalight savings time. There should be multiple lines in the results for such cases, and you would need to read the ''qualifiers'' to see when they apply. Alternatively, maybe substract the offset from some other timezone's offset (i. e. yours) and you might get lucky and they cancel out.

Apparently simple Wikidata SPARQL filter query is slow

Absolute Wikidata and SPARQL beginner here. I am trying to find out the Q code of a particular female name, say Jennifer. I can get it with a query like this:
SELECT ?name WHERE {
?name wdt:P31 wd:Q11879590.
?name rdfs:label ?label.
FILTER((STR(?label)) = "Jennifer")
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
LIMIT 1
That is, I look up entities that are instance of "female given name" and then filter to those with "Jennifer" in the label. It works, but it takes 5 s or more.
If I omit the LIMIT 1 I get many instances of the same results, which signals to me that I am doing something stupid.
Bottom line, is there an efficient way to look up the Q code for a "female given name"?