Union of two selects in a SPARQL query - sparql

I'd like to do something like
{
SELECT ?page, "A" AS ?type WHERE
{
?s rdfs:label "Microsoft"#en;
foaf:page ?page
}
}
UNION
{
SELECT ?page, "B" AS ?type WHERE
{
?s rdfs:label "Apple"#en;
foaf:page ?page
}
}
But this gives a syntax error. How can I union two select queries in SPARQL?

You can union them like this:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT * WHERE
{
{
SELECT ?page ("A" AS ?type) WHERE
{
?s rdfs:label "Microsoft"#en;
foaf:page ?page
}
}
UNION
{
SELECT ?page ("B" AS ?type) WHERE
{
?s rdfs:label "Apple"#en;
foaf:page ?page
}
}
}
(check with the SPARQL validator)
However I don't think you need sub queries at all for this case. For example:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?page ?type WHERE
{
?s foaf:page ?page .
{ ?s rdfs:label "Microsoft"#en . BIND ("A" as ?type) }
UNION
{ ?s rdfs:label "Apple"#en . BIND ("B" as ?type) }
}

Based on #user205512's answer, here's one that works on Virtuoso:
SELECT * {
?s foaf:page ?page .
{
SELECT ?page ("A" AS ?type) {
?s rdfs:label "Microsoft"#en;
foaf:page ?page
}
} UNION {
SELECT ?page ("B" AS ?type) {
?s rdfs:label "Apple"#en;
foaf:page ?page
}
}
}
The trick was just do add an additional ?s foaf:page ?page triple outside of the UNION. This is obviously redundant, but it seems to avoid the Virtuoso bug, which is apparently caused when you have a “naked” UNION with subqueries.

Related

Unable to see Max in SPARQL Query

Im trying to query a knowledge graph and im trying print the max occurrence of ?n in the result and i have tried running following query but it just doesn't prints anything
here is my SPARQL Query
PREFIX : <http://www.tafsirtabari.com/ontology#>
PREFIX RDF:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
select
?n
(MAX( xsd:int(?countOfSharedLikedItems)) as ?max)
(COUNT(?n) as ?countOfSharedLikedItems)
where {
?h :hasTheme :lugha .
?h RDF:type :Hadith .
?h :hasHadithNo ?o.
?p :isPartOfHadith ?h.
{
?p :hasNarratorSegment ?nc.
?nc :refersTo+/:hasName ?n.
}
Union
{
?p :hasRootNarratorSegment ?rnc.
?rnc :refersTo+/:hasName ?n.
}
}
i have also tried following by using group by ?n
PREFIX : <http://www.tafsirtabari.com/ontology#>
PREFIX RDF:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>
select
(MAX(?countOfSharedLikedItems) as ?max)
(COUNT(?n) as ?countOfSharedLikedItems)
where {
?h :hasTheme :lugha .
?h RDF:type :Hadith .
?h :hasHadithNo ?o.
?p :isPartOfHadith ?h.
{
?p :hasNarratorSegment ?nc.
?nc :refersTo+/:hasName ?n.
}
Union
{
?p :hasRootNarratorSegment ?rnc.
?rnc :refersTo+/:hasName ?n.
}
} group by ?n
You can try this
PREFIX : <http://www.tafsirtabari.com/ontology#>
select (COUNT(?o ) AS ?triples) where {
?k :heardFrom ?o
}
6. Which RAWI narrated most hadiths about TOPIC_A
PREFIX hash: <http://www.tafsirtabari.com/ontology#>
PREFIX W3:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX : <http://www.tafsirtabari.com/ontology#>
SELECT ?total WHERE{
select DISTINCT ?n (COUNT(?n) as ?total) where {
?commentary hash:mentions hash:اهل_المعرفه .
?segment hash:containsCommentary ?commentary.
?segment ?Fr ?h .
?h W3:type hash:Hadith.
?p :isPartOfHadith ?h.
{
?p :hasNarratorSegment ?nc.
?nc :refersTo+/:hasName ?n.
}
Union
{
?p :hasRootNarratorSegment ?rnc.
?rnc :refersTo+/:hasName ?n.
}
}GROUP BY ?n
}ORDER BY DESC(?total)
LIMIT 1

How to count references in SPARQL?

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?
General Cleanup
Alternative objects or subjects
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
Alternative properties
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
The specific issue
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)
All right, figured this out as I asked the question. For anyone curious, this was how I modified the query:
SELECT DISTINCT
?subject
?displayId
?version
?name
?description
?type
(COUNT(DISTINCT ?user) as ?uses)
WHERE {
{ ?use sbol2:definition ?subject .
{ ?user sbol2:module ?use } UNION
{ ?user sbol2:component ?use } UNION
{ ?user sbol2:functionalComponent ?use }
} UNION
{ ?user sbol2:model ?subject} UNION
{ ?user sbol2:sequence ?subject } .
{ ?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 . }
} ORDER BY DESC(?uses)
LIMIT 50

sparql count not existing properties as zero

Here is my query:
PREFIX : <http://example.org/ns#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?id ?name (count(?s) as ?count)
WHERE {
?t a :Tag ;
:hasId ?id ;
:hasName ?name
OPTIONAL { ?s :hasTag ?t ;
rdf:type ?type }
FILTER (?type in (:Client, :Project, :Staff))
} GROUP BY ?id ?name
Tags with no objects are not included in the result. How can I get them also without using union?
Performance is also important
The goal is to gather information about tags (id, name) and number of objects they assign to (if no such objects count must be 0). Tag data sample:
:tag912 :hasId "912"^^xsd:integer
:tag912 :hasName "Phones"
This tag is assigned to 6 objects.
This query works for me:
PREFIX : <http://example.org/ns#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?id ?name ?count
WHERE {
{
SELECT ?id ?name (count(?s) as ?count)
WHERE {
?t a :Tag ;
:hasId ?id ;
:hasName ?name .
?s :hasTag ?t ;
rdf:type ?type
FILTER (?type in (:Client, :Project, :Staff))
} GROUP BY ?id ?name
} UNION {
SELECT ?id ?name (0 as ?count)
WHERE {
?t a :Tag ;
:hasId ?id ;
:hasName ?name
FILTER not exists { ?s :hasTag ?t }
}
}
}
How can I use bindings here? Will it improve performance?
Thank you
Why not use UNION?
Aside from that, your query is focused on ?t tags and their ?id and ?name — so it's not surprising that results don't include ?s objects which lack ?t and hence lack any ?id and ?name…
I think this may get you going in the right direction —
PREFIX : <http://example.org/ns#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?id
?name
(count(?s) as ?count)
WHERE
{ ?s rdf:type ?type
FILTER ( ?type IN ( :Client, :Project, :Staff ) ) .
OPTIONAL { ?s :hasTag ?t .
?t rdf:type :Tag ;
:hasId ?id ;
:hasName ?name }
}
GROUP BY ?id ?name
You can check if ?s is bound in your filter:
PREFIX : <http://example.org/ns#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?id ?name (COUNT(?s) as ?count)
WHERE {
?t a :Tag ;
:hasId ?id ;
:hasName ?name .
OPTIONAL {
?s :hasTag ?t ;
rdf:type ?type .
}
FILTER (!BOUND(?s) || ?type in (:Client, :Project, :Staff))
} GROUP BY ?id ?name
I don't know if this is faster than a union (or a bunch of unions), however.

SPARQL DbPedia foaf:name

Trying to execute some queries but when searching for foaf:name resultset is empty. Here's my code:
SELECT DISTINCT ?uri ?string
WHERE {
?uri rdf:type ?x.
?uri foaf:name 'Cavallo domestico'#it .
OPTIONAL { ?uri rdfs:label ?string . FILTER (lang(?string) = 'it') }
}
page exist http://it.dbpedia.org/resource/Equus_caballus/html
Apparently seems it's not related with languages different than english but with foaf:name request. If I execute following, retrieving generic foaf:givenName, it works:
SELECT DISTINCT ?uri ?string
WHERE {
?uri rdf:type ?x.
?uri foaf:givenName 'Jimmy'#en .
OPTIONAL { ?uri rdfs:label ?string . FILTER (lang(?string) = 'en') }
}
I think this wasn't working when I first mentioned that it didn't in a comment, but, as AKSW points out, this seems to be working now. The rdfs:label property has the article titles in various languages, not the foaf:name, so you can do this to get the types of Horse:
select ?x ?type {
?x a ?type ;
rdfs:label "Equus caballus"#it
}
SPARQL results

UNION operator in SPARQL updates

I have two SPARQL updates.First one:
INSERT
{ GRAPH <[http://example/bookStore2]> { ?book ?p ?v } }
WHERE
{ GRAPH <[http://example/bookStore]>
{ ?book dc:date ?date .
FILTER ( ?date > "1970-01-01T00:00:00-02:00"^^xsd:dateTime )
?book ?p ?v
} }
Second:
INSERT
{ GRAPH <[http://example/bookStore2]> { ?book ?p ?v } }
WHERE
{ GRAPH <[http://example/bookStore3]>
{ ?book dc:date ?date .
FILTER ( ?date > "1980-01-01T00:00:00-02:00"^^xsd:dateTime )
?book ?p ?v
} }
Can i combine them with the UNION operator? And if yes, is it an equivalent result? Is it possible to use UNION in SPARQL updates such as in "Select"?
AndyS's answer is correct; you can combine them, and the description of UNION is found in section 7 Matching Alternatives of the SPARQL specification. The combined query would be:
INSERT {
GRAPH <[http://example/bookStore2]> { ?book ?p ?v }
}
WHERE{
{
GRAPH <[http://example/bookStore]> {
?book dc:date ?date .
FILTER ( ?date > "1970-01-01T00:00:00-02:00"^^xsd:dateTime )
?book ?p ?v
}
}
UNION
{
GRAPH <[http://example/bookStore3]> {
?book dc:date ?date .
FILTER ( ?date > "1980-01-01T00:00:00-02:00"^^xsd:dateTime )
?book ?p ?v
}
}
}
In this particular case where the patterns are so similar, you could also just abstract out the differing parts with VALUES:
INSERT {
GRAPH <[http://example/bookStore2]> { ?book ?p ?v }
}
WHERE{
values (?graph ?startDate) {
(<[http://example/bookStore]> "1970-01-01T00:00:00-02:00"^^xsd:dateTime)
(<[http://example/bookStore3]> "1980-01-01T00:00:00-02:00"^^xsd:dateTime)
}
GRAPH ?graph {
?book dc:date ?date .
FILTER ( ?date > ?startDate )
?book ?p ?v
}
}
The WHERE clause is the same as SPARQL Query - you can use UNION.