How can I use CONCAT with results from GROUP_CONCAT in SPARQL? - sparql

I have trouble with a SPARQL query. I have two graphs: Discipline and Professor. The graph Discipline contains different disciplines and is linked with the Professor thanks to his id. For example, I have:
<http://www.rdcproject.com/graph/disciplines> {
<http://www.rdfproject.com/77803>
a <http://www.rdfproject.com/Discipline> ;
<http://www.rdfproject.com/cfu>
"6" ;
<http://www.rdfproject.com/disciplineAbbreviation>
"SE" ;
<http://www.rdfproject.com/disciplinename>
"Software Engineering" ;
<http://www.rdfproject.com/hasCourseof>
<http://www.rdfproject.com/8028> ;
<http://www.rdfproject.com/idDiscipline>
"77803" ;
<http://www.rdfproject.com/isTaughtBy>
<http://www.rdfproject.com/0009004> ,
<http://www.rdfproject.com/0004003> ;
<http://www.rdfproject.com/obligatory>
"false" ;
<http://www.rdfproject.com/semester>
"1" ;
<http://www.rdfproject.com/totalhours>
"50" ;
<http://www.rdfproject.com/weekhours>
"5" ;
<http://www.rdfproject.com/year>
"1" .
}
This course is taught by two professors:
<http://www.rdfproject.com/0009004>
a <http://www.rdfproject.com/Teacher> ;
<http://www.rdfproject.com/firstName>
"Koby" ;
<http://www.rdfproject.com/idProfessor>
"0009004" ;
<http://www.rdfproject.com/lastName>
"Bryant" ;
<http://www.rdfproject.com/role>
"contratto" .
<http://www.rdfproject.com/0004003>
a <http://www.rdfproject.com/Teacher> ;
<http://www.rdfproject.com/firstName>
"Lebron" ;
<http://www.rdfproject.com/idProfessor>
"0004003" ;
<http://www.rdfproject.com/lastName>
"James" ;
<http://www.rdfproject.com/role>
"associato" .
Now I want all professors for all disciplines. I have created this query:
PREFIX uni: <http://www.rdfproject.com/>
PREFIX un: <http://www.w3.org/2007/ont/unit#>
SELECT ?idDiscipline ?disciplineName
(CONCAT('[',GROUP_CONCAT(?idProf;separator=","),', ',GROUP_CONCAT(?firstName;separator=","),', ',GROUP_CONCAT(?lastName;separator=","),', ',GROUP_CONCAT(?role;separator=","),']') as ?professors)
FROM <http://www.rdcproject.com/graph/disciplines>
FROM <http://www.rdcproject.com/graph/professor>
WHERE
{
{
?x a uni:Discipline;
uni:disciplinename ?disciplineName;
uni:idDiscipline ?idDiscipline;
uni:disciplineAbbreviation ?sigleDiscipline;
uni:cfu ?cfu;
uni:hasCourseof ?hasCourseof;
uni:obligatory ?obligatory;
uni:semester ?semester;
uni:totalhours ?totalhours;
uni:weekhours ?weekhours;
uni:year ?year;
uni:isTaughtBy ?isTaughtBy.
?isTaughtBy a uni:Teacher;
uni:idProfessor ?idProf;
uni:firstName ?firstName;
uni:role ?role;
uni:lastName ?lastName.
}
}
GROUP BY ?idDiscipline ?disciplineName
This query works fine if a discipline contains only one professor, but in this case the result is:
ID -> 77803"
NAME -> "Software Engineering"
PROFESSOR -> "[0009004,0004003, Kobe,Lebron, Bryant ,James,
contract,contract]"
How can I get this result?
ID -> 77803"
NAME -> "Software Engineering"
PROFESSOR -> "[0009004, Kobe, Bryant, contract]
[0004003, Lebron,James, contract]
Thanks
EDIT:
Thanks to #AKSW
My new Query is:
PREFIX uni: <http://www.rdfproject.com/>
PREFIX un: <http://www.w3.org/2007/ont/unit#>
SELECT ?idDiscipline ?sigleDiscipline ?disciplineName ?cfu ?hasCourseof ?obligatory ?semester ?totalhours ?weekhours ?year
(GROUP_CONCAT(DISTINCT ?prof_str;separator=",") AS ?Professor)
FROM <http://www.rdcproject.com/graph/disciplines>
FROM <http://www.rdcproject.com/graph/professor>
WHERE
{
{
?x a uni:Discipline;
uni:disciplinename ?disciplineName;
uni:idDiscipline ?idDiscipline;
uni:disciplineAbbreviation ?sigleDiscipline;
uni:cfu ?cfu;
uni:hasCourseof ?hasCourseof;
uni:obligatory ?obligatory;
uni:semester ?semester;
uni:totalhours ?totalhours;
uni:weekhours ?weekhours;
uni:year ?year;
uni:isTaughtBy ?isTaughtBy.
?isTaughtBy a uni:Teacher;
uni:idProfessor ?idProf;
uni:firstName ?firstName;
uni:lastName ?lastName;
uni:role ?role.
}
BIND(CONCAT('[',?idProf,',',?firstName,',',?lastName,',',?role,']') AS ?prof_str)
}
GROUP BY ?idDiscipline ?sigleDiscipline ?disciplineName ?cfu ?hasCourseof ?obligatory ?semester ?totalhours ?weekhours ?year

Related

SPARQL: get object only if predicate exists

I want to get the sources of a dbo:Cheese. Some dbo:Cheese have dbo:Animal as dbp:source. Some others have only text. I would like to get the source information in the ?sources variable regardless of that the source is dbo:Animal or text . How should I do it ?
SELECT ?cheese
CONCAT(GROUP_CONCAT(DISTINCT ?source; SEPARATOR=", "), ", ", GROUP_CONCAT(DISTINCT ?source_label; SEPARATOR=", ")) AS ?sources
WHERE {
?cheese a dbo:Cheese .
optional { # some cheeses don't have a source informed
?cheese dbp:source ?source .
}
optional { # some sources are dbo:Animal, some others are xsd:string
?source a dbo:Animal ;
rdfs:label ?source_label .
FILTER(langMatches(lang(?source_label), "EN"))
}
}
LIMIT 10
I tried this. Problem is that I have both http://dbpedia.org/resource/Sheep and Sheep in ?sources.

Why are some of the classes in my ontolgoy not being returned in my SPARQL query?

I'm rather confused about why I'm receiving too little results (256 expected, 224 returned). When I run the code below, everything returns exactly as I want it, except that I miss all the classes in my ontology which lie at the highest level, or one below the highest level. I don't understand where I'm being too "strict" in my query so that these classes are not being returned in the table. They also all have parent classes (whether that be the topmost class "top concept" of the ontology, or something like an enumeration type class, either way, the leaf should still be found. Would be thankful for tips or pointers where my code might be inadvertently filtering out those classes.
SELECT DISTINCT ?leaf ?parentclasses
WHERE {
GRAPH <>
#a leaf is the lowest level class: A class that does not have a subclass
{
{
{
#I want anything which is a class
{
?leaf rdf:type owl:Class.
}
#i also want the subclass of any superclass if that exists
{
?leaf rdfs:subClassOf ?superclass .
}
#squeezed to specific section of OTL.
filter strstarts(str(?leaf), "URIgoeshere")
#Only keep the results that do not have a preflabel
OPTIONAL {
?leaf skos:prefLabel ?subclasslabel.
}
#make sure the subclasslabel is in dutch
#filter( langMatches(lang(?subclasslabel),"nl") )
#give me the label of the superclass
OPTIONAL {
?superclass skos:prefLabel ?superclasslabel.
}
#make sure it's in dutch
FILTER (lang(?superclasslabel) = "nl")
#if it exists, give me also the superclass of the superclass creating a supersuperclass
{
?superclass rdfs:subClassOf ?supersuperclass.
#give me the label of the supersuperclass
OPTIONAL {
?supersuperclass skos:prefLabel ?supersuperclasslabel.
}
#make sure it's in dutch
FILTER (lang(?supersuperclasslabel) = "nl")
#keep the leafs that are NOT The values whereby the subclass is not empty. (double negative for removing leafs where the subclass has a subclass below it)
FILTER NOT EXISTS {
?subclass rdfs:subClassOf ?leaf
FILTER (?subclass != owl:Nothing )
}
#concatenate the two parentclass variables into one
BIND(concat(str(?superclasslabel), str("-"), str(?supersuperclasslabel) ) as ?parentclasses)
}
}
}
}
}
Here is a ttl file with the same structure as my database: https://file.io/jjwkAWbK4jrF
Below is my end solution to my problem. It was more complicated than I expected, but it works.
The problem was that these classes that didn't have a parent class were not being accepted by the query. With some union cases this could be covered for 0 parent classes, 1 parent class or 2 parent classes.
SELECT DISTINCT ?leaf ?parentclasses
WHERE {
GRAPH <>
#a leaf is the lowest level class: A class that does not have a subclass
{{{{{
#I want anything which is a class
{?leaf rdf:type owl:Class.}
#squeezed
filter strstarts(str(?leaf), "graph")
#keep the leafs that are NOT The values whereby the subclass is not empty.
(double negative for removing leafs where the subclass has a subclass below it)
FILTER NOT EXISTS {?subclass rdfs:subClassOf ?leaf
FILTER (?subclass != owl:Nothing ) }
}
{
{?leaf rdfs:subClassOf ?superclass .}
#grab dutch label if available
optional {
?superclass skos:prefLabel ?superclassnllabel .
filter( langMatches(lang(?superclassnllabel),"nl") )
}
# take either as the label, but dutch over empty
bind( coalesce( ?superclassnllabel, replace(str(?
superclass),"^[^#]*#", "" ) ) as ?superclasslabel )
{
{?superclass rdfs:subClassOf ?supersuperclass.}
#grab dutch label if available
?supersuperclass skos:prefLabel ?supersuperclassnllabel .
filter( langMatches(lang(?supersuperclassnllabel),"nl") )
# take either as the label, but dutch over empty
bind( coalesce( ?supersuperclassnllabel, replace(str(?
supersuperclass),"^[^#]*#", "" ) ) as ?supersuperclasslabel )
BIND(concat(str(?superclasslabel), str(" - "), str(?
supersuperclasslabel) ) as ?parentclasses)
}
union
{
{?superclass ?p ?o.filter(!isblank(?superclass))}
FILTER NOT EXISTS {?superclass rdfs:subClassOf ?supersuperclass}
BIND(concat(str(?superclasslabel), str(" - "), str("Top
Concept") ) as ?parentclasses)
#concatenate the two parentclass variables into one
}
}
}
union
{
#figure this out, WHY IS IT HERE?
{?leaf rdf:type owl:Class .filter(!isblank(?leaf))}
FILTER strstarts(str(?leaf), "graph")
FILTER NOT EXISTS {?leaf rdfs:subClassOf ?superclass}
FILTER NOT EXISTS {?subclass rdfs:subClassOf ?leaf
FILTER (?subclass != owl:Nothing ) }
BIND (str("Top Class") as ?parentclasses )
}
}}}}

SPARQL FILTER() using Jena not working properly

i'm running Ontology project on Netbeans using Jena for SPARQL (version 2.6.2 ) Queries, and now i'm trying to FILTERS for Temperature , this code doesn't work as expected and return no result
PREFIX ns: <http://www.semanticweb.org/pavilion/ontologies/2017/5/untitled-ontology-66#>
SELECT ?StarName ?Temperature
WHERE {
?star a ns:Star ;
ns:possessesSpectralType ?SpectralType ;
ns:possessesStarName ?StarName ;
ns:possessesTemperature ?Temperature .
FILTER (?Temperature > 10 ).
}
on the other hand i've tried this code and it works but only with Equal operator
PREFIX ns: <http://www.semanticweb.org/pavilion/ontologies/2017/5/untitled-ontology-66#>
SELECT ?star
WHERE {
?star a ns:Star ;
ns:possessesSpectralType ?SpectralType ;
ns:possessesStarName ?StarName ;
ns:possessesTemperature ?Temperature .
FILTER (?Temperature = ns:168 )
}

SPARQL - how to do a join operation

I have a model, where I have 3 classes:
SR - <http://data.sample.com/vocab/StudentRecord>
HCVR - <http://data.sample.com/vocab/HealthCenterVisitRecord>
CR - <http://data.sample.com/vocab/ClassRoom>
StudentRecord has a property classRoom.
HealthCenterVisitRecord has a property studentRecord.
Given a particular ClassRoom URI, how do I find all the StudentRecords, who are properties of HealthCenterVisitRecords.
Query that I tried (The initial part of the query fetches the student belonging to a ClassRoom, but the second part is screwed up and I know it):
SELECT ?hcvr
WHERE {
?sr rdf:type <http://data.sample.com/vocab/StudentRecord>.
?sr <http://data.sample.com/vocab/classRoom> <http://data.sample.com/resource/ClassRoom/1156>.
?sr <http://data.sample.com/vocab/healthCentreVisitRecord> ?hcvr.
}
Another query I tried:
SELECT DISTINCT ?sr WHERE {
{
?sr rdf:type <http://data.sample.com/vocab/StudentRecord>.
?sr <http://data.latize.com/vocab/classRoom> <http://data.latize.com/resource/ClassRoom/1156>.
}
UNION
{
?hcvr rdf:type <http://data.sample.com/vocab/HealthCentreVisitRecord>.
?hcvr <http://data.sample.com/vocab/studentRecord> ?sr.
}
}
LIMIT 1000
Figured it out, here is the query:
SELECT ?hcvr
WHERE {
?sr rdf:type <http://data.sample.com/vocab/StudentRecord>.
?sr <http://data.sample.com/vocab/classRoom> <http://data.sample.com/resource/ClassRoom/1156>.
?hcvr rdf:type <http://data.sample.com/vocab/healthCentreVisitRecord>.
?hcvr <http://data.sample.com/vocab/studentRecord> ?sr.
}

How to choose a different query based on the subject of an object in SPARQL?

Let's say I have the following data
subject = david
predicate = knows
object1 = Amy
object2 = Brian
subject = Amy
predicate = gender
object = female
subject = Brian
predicate = gender
object = male
Now I want to find all the people david knows but perform different queries based upon their gender so the pseudocode would look something like this:
SELECT ?something
WHERE{
david rdf:knows ?person
if{?person rdf:gender "female"}
{ do this query}
else if {?person rdf:gender "male"}
{do this query}
}
From what I've seen SPARQL if statements can only print out information and cannot be used to make decisions on what query to execute.
If anyone knows how the above can be achieved I would be most grateful.
In this case, you could do something like:
select ?something where {
:David :knows ?person
optional {
?person :gender "female" .
#-- more query
}
optional {
?person :gender "male" .
#-- more query
}
}
Both of the optional parts are optional, and only the one with the matching gender will be able to match, so it's essentially a conditional query. Note that you'll do both if you have data like :person :gender "male", "female", and that you'll do neither if you don't have a gender provided.