I want to find the number of times that each subject returned by this query is the object of another triple.
I can use the following example to select everything I want without the count that I want as well.
SELECT DISTINCT
?subject
?displayId
?version
?name
?description
?type
WHERE {
{ ?subject a sbol2:ComponentDefinition } UNION
{ ?subject a sbol2:ModuleDefinition } UNION
{ ?subject a sbol2:Collection } UNION
{ ?subject a sbol2:Sequence } UNION
{ ?subject a sbol2:Model } .
?subject a ?type
OPTIONAL { ?subject sbol2:displayId ?displayId . }
OPTIONAL { ?subject sbol2:version ?version . }
OPTIONAL { ?subject dcterms:title ?name . }
OPTIONAL { ?subject dcterms:description ?description . }
}
LIMIT 50
I can add in the following criteria to limit my query to things that are only related to an example object, in this case, the object with URI <http://localhost:7777/public/test/U49845/1>
.
{ ?use sbol2:definition <http://localhost:7777/public/test/U49845/1> .
{ ?subject sbol2:module ?use } UNION
{ ?subject sbol2:component ?use } UNION
{ ?subject sbol2:functionalComponent ?use }
} UNION
{ ?subject sbol2:model <http://localhost:7777/public/test/U49845/1> } UNION
{ ?subject sbol2:sequence <http://localhost:7777/public/test/U49845/1> } .
Is there a way to get the number of items that the second query would return for every ?subject
in the first query?
First, note that this union block
{ ?subject a sbol2:ComponentDefinition } UNION
{ ?subject a sbol2:ModuleDefinition } UNION
{ ?subject a sbol2:Collection } UNION
{ ?subject a sbol2:Sequence } UNION
{ ?subject a sbol2:Model } .
can be much shorter using values:
values ?type { sbol2:ComponentDefinition sbol2:ModuleDefinition
sbol2:Collection sbol2:Sequence sbol2:Model }
?subject a ?type
Similarly, if you've got a bunch of alternative properties, just use a property path. This union:
{ ?subject sbol2:module ?use } UNION
{ ?subject sbol2:component ?use } UNION
{ ?subject sbol2:functionalComponent ?use }
is equivalent to
?subject sbol2:module|sbol2:component|sbol2:functionalComponent ?use
So, turning the query you came up with into legal SPARQL by adding the required group by, you end up with:
SELECT DISTINCT
?subject ?displayId ?version ?name ?description ?type
(COUNT(DISTINCT ?user) as ?uses)
WHERE {
#-- Find users of the subject.
?user ((sbol2:module|sbol2:component|sbol2:functionalComponent)
/sbol2:definition)|sbol2:model|sbol2:sequence ?subject .
#-- Find subjects
values ?stype { sbol2:ComponentDefinition sbol2:ModuleDefinition
sbol2:Collection sbol2:Sequence sbol2:Model }
?subject a ?stype .
#-- Find other types and properties of the ?subject
?subject a ?type .
OPTIONAL { ?subject sbol2:displayId ?displayId . }
OPTIONAL { ?subject sbol2:version ?version . }
OPTIONAL { ?subject dcterms:title ?name . }
OPTIONAL { ?subject dcterms:description ?description . }
}
GROUP BY ?subject ?displayId ?version ?name ?description ?type
ORDER BY DESC(?uses)