aluriak
aluriak

Reputation: 5867

Access the property of a property

I have the following query, that I ran on the wikidata query service web interface:

SELECT ?objectLabel ?mass
WHERE {
  ?object wdt:P397 wd:Q525.  # the object should have the sun as parent astronomical body
  ?object wdt:P31 ?status.
  ?object wdt:P2067 ?mass.

  # Here are the accepted object status
  VALUES ?status {wd:Q128207 wd:Q121750 wd:Q1319599}.  # terrestrial planet, gas giant, ice giant

  # automatically use the english label for ?xLabel variables 
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
} 

I found that the mass value is given in a specific unit, yottagram in case of the Earth. How can I access this information ?

I tried to add something like:

?mass   wdt:P2237 ?mass_unit.

But, expectedly, this doesn't work because ?mass is an integer, not an object referencing the Earth mass. Using the property itself as a subject doesn't work neither:

?object wdt:P2067 ?mass.
wd:P2067 wdt:P2237 ?massUnit.

This returns all tuples with all available units. (Earth is associated with 5972.37 kilograms, 5972.37 yottagrams, 5972.37 solar mass, etc)

Also, chaining the properties leads to no results:

?object wdt:P2067/wdt:P2237 ?massUnit.

I imagine that I need to use, not the property itself, but an instance of it linking specifically the Earth and the integer that describes its mass.

How access the unit information ? (in case of Earth, Yottagram)

Upvotes: 5

Views: 383

Answers (2)

svick
svick

Reputation: 244998

How Wikidata is represented in RDF (and thus in SPARQL) is described at MediaWiki.org page Wikibase/Indexing/RDF Dump Format.

The relevant part is that, in your case, wdt:P2067 directly gives you just the value, but if you instead use p:P2067, you get the whole statement. From there, you can use psv:P2067 to get a value node. And from there, you can use wikibase:quantityAmount to get the mass (just like you could with wdt:P2067), but you can also use wikibase:quantityUnit to get the entity representing the unit.

So, the whole query could look like this:

SELECT ?objectLabel ?mass ?massUnitLabel
WHERE {
  ?object wdt:P397 wd:Q525.  # the object should have the sun as parent astronomical body
  ?object wdt:P31 ?status.

  ?object p:P2067/psv:P2067 ?massValue.
  ?massValue wikibase:quantityAmount ?mass.
  ?massValue wikibase:quantityUnit ?massUnit.

  # Here are the accepted object status
  VALUES ?status {wd:Q128207 wd:Q121750 wd:Q1319599}.  # terrestrial planet, gas giant, ice giant

  # automatically use the english label for ?xLabel variables 
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
}

If you wanted, you could eliminate the ?massValue variable by using the following code:

?object p:P2067/psv:P2067 [
  wikibase:quantityAmount ?mass;
  wikibase:quantityUnit ?massUnit ] 

Upvotes: 5

scotthenninger
scotthenninger

Reputation: 4001

RDF literals are typed by XSD datatypes, and SPARQL's datatype() can be used to find the type. So try this in your SELECT statement to find the type for ?mass:

SELECT ?objectLabel ?mass (datatype(?mass) AS ?masstype)
....

Upvotes: 0

Related Questions