Search code examples
sparqlprotegerdfslinked-data

Finding classes which should be instances sparql; Finding classes with exactly 1 subclass


It sounds quite simple but I have not managed to find a nice solution yet. I'm looking to find the classes in my ontology which have exactly one subclass.

So far I have approached it as follows:

SELECT (COUNT(?anything) AS ?count) ?class
WHERE {
GRAPH <> {

    ?class rdf:type owl:Class.
    ?class rdfs:subClassOf ?anything.
    ?anything rdf:type owl:Class.
   
} group by ?class 

I should then theoretically be able to sort on count, and the results that have value 1 should have only have 1 subclass. However, when I execute this query, the counts do not correspond with what I expect at all e.g. my test case should return 1, which it does, but another class which doesn't have a subclass at all, also returns 1. And a class with 3 subclasses returns a count of 4.

in the image below, it should find that the highlighted classes have a count of 1. picture of class structure


Solution

  • The SPARQL query you're looking for would be something like

    SELECT ?class WHERE {
      ?sub rdfs:subClassOf ?class
    }
    GROUP BY ?class 
    HAVING (COUNT(DISTINCT ?sub) = 1)
    

    As UninformedUser mentioned in a comment, though, if there is OWL inference available, there can be lots of answers that you might not be expecting, such as

    owl:Nothing rdfs:subClassOf ex:YourClass
    

    and

    ex:YourClass rdfs:subClassOf ex:YourClass
    

    If those keep the query from producing the kind of results you're looking for, you should add a filter like

    SELECT ?class WHERE {
      ?sub rdfs:subClassOf ?class
      FILTER ( ?sub != ?class && ?sub != owl:Nothing )
    }
    GROUP BY ?class 
    HAVING (COUNT(DISTINCT ?sub) = 1)