I'm learning SPARQL and I'm trying to do a query on a movie ontology I wrote myself. I would like to extract from it all the the actors who worked together in a movie, so I wrote this:
PREFIX exID: <http://example.org/#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT DISTINCT ?actorName1 ?actorName2
WHERE {
?actor rdfs:label ?actorName1 .
?actor exID:recitaIn ?movie .
{
SELECT DISTINCT ?actorName2 ?movie2
WHERE {
?actor2 rdfs:label ?actorName2 .
?actor2 exID:recitaIn ?movie2 .
}
}
FILTER (?movie = ?movie2 && ?actorName1 != ?actorName2)
}
Now this works, but not really in the way I want, because it writes two times the same actors but in opposite order. To be more clear, this will have as output:
actorName1 | actorName2 |
---|---|
"Jack Nicholson" | "Leonardo DiCaprio" |
"Leonardo DiCaprio" | "Jack Nicholson" |
but I would like to have just one of this two rows because they represents conceptually the same thing. How can I accomplish this?
I will leave the significant part of the ontology here:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ontology [
<!ENTITY xsd "http://www.w3.org/2001/XLMSchema#">
]>
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
xmlns:owl ="http://www.w3.org/2002/07/owl#"
xmlns:xsd ="http://www.w3.org/2001/XLMSchema#"
xml:base="http://example.org/"
xmlns:exID="http://example.org/#"
>
<!-- Ontology Properties -->
<owl:Ontology rdf:about="">
</owl:Ontology>
<!-- Class declarations -->
<owl:Class rdf:about="#Regista">
<rdfs:label xml:lang="it">Regista</rdfs:label>
<rdfs:label xml:lang="en">Director</rdfs:label>
<rdfs:comment xml:lang="it">Responsabile artistico e tecnico di un'opera</rdfs:comment>
<rdfs:comment xml:lang="en">Artistic and technical manager of a creative work</rdfs:comment>
</owl:Class>
<owl:Class rdf:about="#Troupe">
<rdfs:label xml:lang="it">Troupe</rdfs:label>
<rdfs:label xml:lang="en">Troupe</rdfs:label>
<rdfs:comment xml:lang="it">L'insieme delle figure professionali, tecniche, artistiche ed amministrative che realizzano un film</rdfs:comment>
<rdfs:comment xml:lang="en">The group of professional, technical and artistics figures which realize a movie</rdfs:comment>
</owl:Class>
<owl:Class rdf:about="#Cast">
<rdfs:subClassOf rdf:resource="#Troupe" />
<rdfs:label xml:lang="it">Cast</rdfs:label>
<rdfs:label xml:lang="en">Cast</rdfs:label>
<rdfs:comment xml:lang="it">L'insieme degli attori che compaiono nel film</rdfs:comment>
<rdfs:comment xml:lang="en">Ensemble of the actors who appear in the movie</rdfs:comment>
</owl:Class>
<owl:Class rdf:about="#Attore">
<rdfs:subClassOf rdf:resource="#Cast" />
<rdfs:label xml:lang="it">Attore</rdfs:label>
<rdfs:label xml:lang="en">Actor</rdfs:label>
<rdfs:comment xml:lang="it">Rappresenta un personaggio in un'opera creativa</rdfs:comment>
<rdfs:comment xml:lang="en">Portrays a character in a creative work</rdfs:comment>
</owl:Class>
<owl:Class rdf:about="#Film">
<rdfs:label xml:lang="it">Film</rdfs:label>
<rdfs:label xml:lang="en">Movie</rdfs:label>
<rdfs:comment xml:lang="it">Un lavoro di arte visuale utilizzato per simulare esperienze che comunica idee, storie, percezioni, sentimenti, bellezza o atmosfera tramite l'utilizzo di immagini in movimento.</rdfs:comment>
<rdfs:comment xml:lang="en">A work of visual art used to simulate experiences that communicate ideas, stories, perceptions, feelings, beauty, or atmosphere through the use of moving images.</rdfs:comment>
</owl:Class>
<owl:Class rdf:about="#Pellicola">
<rdfs:label xml:lang="it">Pellicola</rdfs:label>
<rdfs:label xml:lang="en">Movie</rdfs:label>
<owl:equivalentClass rdf:resource="#Film" />
</owl:Class>
<owl:Class rdf:about="#Attore_Comico">
<rdfs:label xml:lang="it">Attore Comico</rdfs:label>
<rdfs:label xml:lang="en">Comic Actor</rdfs:label>
<rdfs:comment xml:lang="it">Un attore che prova a intrattenere il pubblico facendolo ridere</rdfs:comment>
<rdfs:comment xml:lang="en">An actor who seeks to entertain an audience by making them laugh</rdfs:comment>
<rdfs:subClassOf rdf:resource="#Attore" />
</owl:Class>
<owl:Class rdf:about="#Attore_Drammatico">
<rdfs:label xml:lang="it">Attore Drammatico</rdfs:label>
<rdfs:label xml:lang="en">Dramatic Actor</rdfs:label>
<rdfs:comment xml:lang="it">Un attore specializzato in ruoli dal forte sviluppo psicologico ed emotivo</rdfs:comment>
<rdfs:comment xml:lang="en">An actor specialized in roles with an huge psychological and emotional development</rdfs:comment>
<rdfs:subClassOf rdf:resource="#Attore" />
</owl:Class>
<!-- Properties declarations -->
<owl:ObjectProperty rdf:about="#dirige">
<rdfs:domain rdf:resource="#Regista" />
<rdfs:range rdf:resource="#Film" />
</owl:ObjectProperty>
<owl:ObjectProperty rdf:about="#compareIn">
<rdfs:domain rdf:resource="#Attore" />
<rdfs:range rdf:resource="#Film" />
</owl:ObjectProperty>
<owl:ObjectProperty rdf:about="#recitaIn">
<rdfs:subPropertyOf rdf:resource="#compareIn" />
</owl:ObjectProperty>
<!-- Instances -->
<rdf:Description rdf:about="theWolfOfWallStreet">
<rdfs:label>The Wolf Of Wall Street</rdfs:label>
<rdf:type rdf:resource="#Film"/>
</rdf:Description>
<rdf:Description rdf:about="theDeparted">
<rdfs:label>The Departed</rdfs:label>
<rdf:type rdf:resource="#Film"/>
</rdf:Description>
<rdf:Description rdf:about="gangsNY">
<rdfs:label>Gangs of New York</rdfs:label>
<rdf:type rdf:resource="#Film"/>
</rdf:Description>
<rdf:Description rdf:about="aviator">
<rdfs:label>The Aviator</rdfs:label>
<rdf:type rdf:resource="#Film"/>
</rdf:Description>
<rdf:Description rdf:about="killersFlowerMoon">
<rdfs:label>Killers of the Flower Moon</rdfs:label>
<rdf:type rdf:resource="#Film"/>
</rdf:Description>
<rdf:Description rdf:about="shutterIsland">
<rdfs:label>Shutter Island</rdfs:label>
<rdf:type rdf:resource="#Film"/>
</rdf:Description>
<rdf:Description rdf:about="diCaprio">
<rdfs:label>Leonardo di Caprio</rdfs:label>
<rdf:type rdf:resource="#Attore_Drammatico"/>
<rdf:type rdf:resource="#Attore_Comico"/>
<exID:recitaIn rdf:resource="theWolfOfWallStreet"/>
<exID:recitaIn rdf:resource="theDeparted"/>
<exID:recitaIn rdf:resource="gangsNY"/>
<exID:recitaIn rdf:resource="aviator"/>
<exID:recitaIn rdf:resource="shutterIsland"/>
<exID:recitaIn rdf:resource="killersFlowerMoon"/>
</rdf:Description>
<rdf:Description rdf:about="nicholson">
<rdfs:label>Jack Nicholson</rdfs:label>
<rdf:type rdf:resource="#Attore_Drammatico"/>
<rdf:type rdf:resource="#Attore_Comico"/>
<exID:recitaIn rdf:resource="theDeparted"/>
</rdf:Description>
<rdf:Description rdf:about="scorsese">
<rdfs:label>Martin Scorsese</rdfs:label>
<rdf:type rdf:resource="#Regista"/>
<exID:dirige rdf:resource="theWolfOfWallStreet"/>
<exID:dirige rdf:resource="theDeparted"/>
<exID:dirige rdf:resource="gangsNY"/>
<exID:dirige rdf:resource="shutterIsland"/>
<exID:dirige rdf:resource="aviator"/>
<exID:dirige rdf:resource="killersFlowerMoon"/>
</rdf:Description>
<owl:AllDifferent>
<owl:distinctMembers rdf:parseType="Collection">
<exID:Attore rdf:about="diCaprio" />
<exID:Attore rdf:about="nicholson" />
</owl:distinctMembers>
</owl:AllDifferent>
</rdf:RDF>
The correct answer for my problem was in the comment by UninformedUser:
?actor rdfs:label ?actorName1 .
?actor exID:recitaIn ?movie .
?actor2 rdfs:label ?actorName2.
?actor2 exID:recitaIn ?movie .
Without any subquery at all. This will correctly display:
actorName1 | actorName2 |
---|---|
"Jack Nicholson" | "Leonardo DiCaprio" |
as output, without any duplicates.