13

Here is my naive query for bridges:

SELECT ?item WHERE {
    ?item wdt:P31 wd:Q12280.  # Item's type is: bridge
}

Problem: It only returns a small fraction of all bridges, because railway bridges (and all other subclasses of "bridge") are not counted.

How to retrieve all items, including sub-classes/sub-sub-classes/etc?
It MUST be with SPARQL.

Nicolas Raoul
  • 8,426
  • 5
  • 28
  • 61

2 Answers2

15

The right expression to use here is p:P31/ps:P31/wdt:P279*.

Explanation:

  • p:P31/ps:P31 means instance of, or instance of not marked as preferred. Only using p:P31 at this step would miss some instance.
  • Following the "instance of" part, /wdt:P279* means this class or of any of its sub-classes/sub-sub-classes/etc

So, it means instance of this class or of any of its sub-classes/sub-sub-classes/etc.

The request becomes:

SELECT ?item WHERE {
    ?item p:P31/ps:P31/wdt:P279* wd:Q12280.  # Item's type is: bridge or sub-type or sub-sub-type/etc
}

Try this query on query.wikidata.org

Nicolas Raoul
  • 8,426
  • 5
  • 28
  • 61
  • Then rather p:P31/ps:P31/(p:P279/ps:P279)*. Unfortunately, it's very slow and there is no way to optimize it. One could write p:P31/ps:P31/(p:P279|ps:P279)* instead, relying on the Wikidata data model. – Stanislav Kralin Feb 07 '19 at 10:09
2

Something like

SELECT  ?item  ?type ?typeLabel WHERE {
    ?type (a | wdt:P279) wd:Q12280.  # Item's type is subclass of bridge
    ?item wdt:P31 ?type.
     SERVICE wikibase:label {
    bd:serviceParam wikibase:language "en" .
       }
}
order by ?item

In this specific case it seems that all instances have a more specific type but may have multiple types. So you may want to `SELECT DISTINCT ?item.

Correct query

    SELECT DISTINCT ?item   WHERE {
 {   ?type wdt:P279 wd:Q12280.  # Item's type is subclass of bridge 
     ?item wdt:P31 ?type. }
UNION
 { ?item wdt:P31 wd:Q12280.} # item is an instance of bridge 
 }

DISTINCT required as entities may be instances of a bridge and one of its subclasses. Logically they all should be but apparently that's not how it's done in Wikidata.

chrisis
  • 388
  • 2
  • 13
  • 1
    I just noticed a problem. This seems to get only sub-classes (so, only railway bridge, suspended bridges, but not item that are simply bridges). How to include all? – Nicolas Raoul Sep 13 '16 at 09:20
  • 1
    The second query does not get sub-sub-classes, for instance Suspended wooden bridges. – Nicolas Raoul Apr 05 '17 at 10:31