Question

This question seemed easy to me until I tried it... but it's also possible that I'm just thinking about the problem incorrectly.

Let's say we've arbitrarily gotten 100 subjects out of dbpedia.

SELECT ?s
WHERE {
  ?s ?p ?o .
}
LIMIT 100

What I'd like to do is add a column that says whether they are a Person, Place, or SomeOtherType, and if none of those things, "null".

So, there are a couple ways I've tried to approach this:

  1. using rdf:type and VALUES:

    SELECT ?s ?ppt
    WHERE {
      ?s rdf:type ?ppt .
      VALUES ?ppt {
        dbpedia-owl:Person
        dbpedia-owl:Place
        dbpedia-owl:SomeOtherType
      }
    }
    

    But this simply gets a list of subjects that have that value, and isn't necessarily answering the question of which of the three types they are (i.e. if I have 1 subject, say in place of ?s, I can't just add the VALUES { ... } block to a query against that 1 subject, because if it isn't any of the three, then there will be zero results returned.

  2. I could BIND ( IF ... ELSE ... etc ) AS ?ppt, but that seems a bit weird, too.

So, which query functions should I use to determine which of the three (four if you count "null") types something belongs to, if at all?

Was it helpful?

Solution

I think that a solution with bind( if(...), ..., ...) makes sense here. It doesn't feel particularly strange. Suppose you have data like this, where :A and :B are the types of interest.

@prefix : <http://stackoverflow.com/q/22289078/1281433/> .

:i1 :name "i1" . # no type
:i2 a :A .       
:i3 a :B .       
:i4 a :A, :B .   
:i5 a :C .       
:i6 a :B, :C .

I've intentionally added some corner cases to clarify what happens. Since :i1 has no type at all, we won't see it in the results. Since :i2 and :i3 each have one "type of interest" they each appear in the results once. :i4 has both types of interest, so it will appear in the results twice, once for each interesting type. :i5 has no type of interest, so it will appear with an empty type (I used an unbound variable, a technique discussed in an answers.sematicweb.com question and answer, Binding a variable only when another is non-blank?). :i6 has a type of interest and an uninteresting type, so it will appear once with an interested type, and once with a blank value.

prefix : <http://stackoverflow.com/q/22289078/1281433/>

select ?i ?type where { 
  ?i a ?_type . 
  bind( if( ?_type in (:A, :B), ?_type, ?noType ) as ?type )
}
--------------
| i   | type |
==============
| :i2 | :A   |
| :i3 | :B   |
| :i4 | :A   |
| :i4 | :B   |
| :i5 |      |
| :i6 |      |
| :i6 | :B   |
--------------
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top