SPARQL different operator - sparql

SPARQL Query
I have some SPARQL query shown below:
SELECT DISTINCT ?name1
WHERE {
GRAPH <blabla>
{
?k swrc:author ?x .
?x foaf:name ?name1 .
} .
GRAPH <blabla2>
{
?l swrc:author ?y .
?y foaf:name ?name2 .
} .
FILTER(?x != ?y) .
}
I want to get the names that exist only in the first graph blabla.
Problem
Counter intuitively I get some names that actually belong to the intersection. This happens because b (of set A) = b (of set B)?
Question
What are exactly the semantics of != ? How can I surpass this problem?

The semantics of != are exactly that its left argument is not equal to its right argument. But a FILTER is evaluated for every possible combination of values - so the query as you formulated it will return all name-values of ?x for which some value of ?y is not equal to it.
If you want to get back only name-values of ?x for which all values of ?y are not equal to it, you should be using a NOT EXISTS clause:
SELECT DISTINCT ?name1
WHERE {
GRAPH <blabla>
{
?k swrc:author ?x.
?x foaf:name ?name1.
}
FILTER NOT EXISTS {
GRAPH <blabla2>
{
?l swrc:author ?x.
}
}
}
Note that using this approach you can actually get rid of variable ?y altogether: you change the condition to just check that author ?x as found in the first graph does not also occur in the second graph.

Related

SPARQL returning empty result when passing MIN(?date1) from subquery into outer query, with BIND((YEAR(?minDate) - YEAR(?date2)) AS ?diffDate)

<This question is now resolved, see comment by Valerio Cocchi>
I am trying to pass a variable from a subquery, that takes the minimum date of a set of dates ?date1 belonging to ?p and passes this to the outer query, which then takes another date ?date2 belonging to ?p (there can be at most 1 ?date2 for every ?p) and subtracts ?minDate from ?date2 to get an integer value for the number of years between. I am getting a blank value for this, i.e. ?diffDate returns no value.
I am using Fuseki version 4.3.2. Here is an example of the query:
SELECT ?p ?minDate ?date2 ?diffDate
{
?p a abc:P;
abc:hasAnotherDate ?date2.
BIND((YEAR(?minDate) - YEAR(?date2)) AS ?diffDate)
{
SELECT ?p (MIN(?date1) as ?minDate)
WHERE
{
?p a abc:P;
abc:hasDate ?date1.
} group by ?p
}
}
and an example of the kind of result I am getting:
|-?p----|-----------------?minDate-------------|-----------------?date2------------- |?diffDate|
|<123>|20012-11-22T00:00:00"^^xsd:dateTime|2008-08-18T00:00:00"^^xsd:dateTime| |
I would expect that ?diffDate would give me an integer value. Am I missing something fundamental about how subqueries work in SPARQL?
It seems you have encountered quite an obscure part of the SPARQL spec, namely how BIND works.
Normally SPARQL is evaluated without regard for the position of atoms, i.e.
SELECT *
WHERE {
?a :p1 ?b .
?b :p2 ?c .}
is the same query as:
SELECT *
WHERE {
?b :p2 ?c .
?a :p1 ?b .}
However, BIND is position dependent, so e.g.:
SELECT *
WHERE {
?a :p1 ?b .
BIND(:john AS ?a)}
is not a valid query, whereas:
SELECT *
WHERE {
BIND(:john AS ?a)
?a :p1 ?b .
}
is entirely valid. The same applies to variables used inside of the BIND, which must be declared before the BIND appears.
See here for more.
To go back to your problem, your BIND is using the ?minDate variable before it has been bound, which is why it fails to produce a value for ?diffDate.
This query should do the trick:
SELECT ?p ?minDate ?date2 ?diffDate
{
?p a abc:P;
abc:hasAnotherDate ?date2.
{
SELECT ?p (MIN(?date1) as ?minDate)
WHERE
{
?p a abc:P;
abc:hasDate ?date1.
} group by ?p
}
BIND((YEAR(?minDate) - YEAR(?date2)) AS ?diffDate) #Put the BIND after all the variables it uses are bound.
}
Alternatively, you could evaluate the difference in the SELECT, like so:
SELECT ?p ?minDate ?date2 (YEAR(?minDate) - YEAR(?date2) AS ?diffDate)
{
?p a abc:P;
abc:hasAnotherDate ?date2.
{
SELECT ?p (MIN(?date1) as ?minDate)
WHERE
{
?p a abc:P;
abc:hasDate ?date1.
} group by ?p
}
}

SPARQL - FILTER NOT EXISTS vs MINUS

Could anyone please explain to me the difference between FILTER NOT EXISTS and MINUS in sparql. Specifically, when they don't contain WHERE variables in their body.
For example why does the following query returns anything?
SELECT * {
?s ?p ?o .
FILTER NOT EXISTS { ?x ?y ?z } .
}
and why does the following query returns everything?
SELECT * {
?s ?p ?o .
MINUS { ?x ?y ?z } .
}
Thanks in advance

What does !a mean in SPARQL?

I'm using SPARQL to construct a query and would like to rule out certain results.
I'm aware FILTER NOT EXISTS can be used to do the task. For example:
SELECT * {
?sub a ?type .
FILTER NOT EXISTS {?sub a :NotExpectedType.}
}
But during exploration, I accidentally found I could write !a. That's a valid SPARQL query, but the result is different from FILTER NOT EXISTS. For example:
SELECT * {
?sub a ?type .
?sub !a :NotExpectedType .
}
So what does the !a mean? (I'm aware a is a shortcut for rdf:type, but that doesn't help me understanding yet.)
!a is a property path, and it means “a path of length one with a property other than rdf:type”.
SELECT ?x {
?x a ?type.
FILTER NOT EXISTS { ?x a :MyClass }
}
The query above will find the ?x where no triple ?x rdf:type :MyClass exists.
SELECT ?x {
?x a ?type.
?x !a :MyClass.
}
This query will find the ?x where a triple ?x ?property :MyClass exists for some ?property other than rdf:type.

Sparql delete entity and all its linked elements

I have a Fuseki DB with triples like the following:
<https://tomcat.antudo.it/data/bucket.json-WSP1WS8#row=1>
<https://tomcat.antudo.it/data/bucket.json-WSP1WS8#ws7col0>
"ws6dat1aa"
...
<https://tomcat.antudo.it/data/bucket.json-WSP1WS8#row=2>
<https://tomcat.antudo.it/data/bucket.json-WSP1WS8#ws6col2>
"ws6dat2aa"
...
<http://www.w3.org/2002/07/owl#bottomDataProperty>
<http://www.w3.org/2002/07/owl#propertyDisjointWith>
<https://tomcat.antudo.it/data/bucket.json-WSP1WS8#ws7col0>
I want to delete everything related to:
<https://tomcat.antudo.it/data/bucket.json-WSP1WS8#row=1>
The problem is that i'm not able to write a query that also target triples like that one:
<http://www.w3.org/2002/07/owl#bottomDataProperty>
<http://www.w3.org/2002/07/owl#propertyDisjointWith>
<https://tomcat.antudo.it/data/bucket.json-WSP1WS8#ws7col0>
I have used the following query to delete triples about a list of entities:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
DELETE {
?x ?y ?z
}
WHERE {
{
?x ?y ?z.
?x rdfs:seeAlso <https://tomcat.antudo.it/data/#dcat_test.csv-WSP1WS6>.
}
union
{
?x ?y ?z.
?x rdfs:seeAlso <https://tomcat.antudo.it/data/#dcat_test.csv-WSP1WS7>.
}
}
I think i have to do something similar to that:
SPARQL: Delete instance and all of its properties with linked subproperties but i'm stuck. Any help will be appreciated
The following should work if you want to delete the resource entirely from the graph. Note that you need to remove the triples "both ways".
DELETE {
<https://tomcat.antudo.it/data/bucket.json-WSP1WS8#row=1> ?p ?o .
?s1 ?p1 <https://tomcat.antudo.it/data/bucket.json-WSP1WS8#row=1> .
}
WHERE {
<https://tomcat.antudo.it/data/bucket.json-WSP1WS8#row=1> ?p ?o .
OPTIONAL {
?s1 ?p1 <https://tomcat.antudo.it/data/bucket.json-WSP1WS8#row=1> .
}
}

Simplify SPARQL query

I’m trying to make a rather complex call to DBPedia using a SPARQL query. I’d like to get some information about a city (district, federal state/»Bundesland«, postal codes, coordinates and geographically related cities).
Try online!
SELECT * WHERE {
#input
?x rdfs:label "Bentzin"#de.
#district
OPTIONAL {
?x dbpedia-owl:district ?district
# ?x dbpprop:landkreis ?district
{ SELECT * WHERE {
?district rdfs:label ?districtName
FILTER(lang(?districtName) = "de")
?district dbpprop:capital ?districtCapital
{ SELECT * WHERE {
?districtCapital rdfs:label ?districtCapitalName
FILTER(lang(?districtCapitalName) = "de")
}}
}}
}
#federal state
OPTIONAL {
# ?x dbpprop:bundesland ?land
?x dbpedia-owl:federalState ?land
{ SELECT * WHERE {
?land rdfs:label ?landName
FILTER(lang(?landName) = "de")
}}
}
#postal codes
?x dbpedia-owl:postalCode ?zip.
#coordinates
?x geo:lat ?lat.
?x geo:long ?long
#cities in the south
OPTIONAL {
?x dbpprop:south ?south
{SELECT * WHERE {
?south rdfs:label ?southName
FILTER(lang(?southName) = "de")
}}
}
#cities in the north
OPTIONAL {
?x dbpprop:north ?north
{ SELECT * WHERE {
?north rdfs:label ?northName
FILTER(lang(?northName) = "de")
}}
}
#cities in the west
...
}
This works in some cases, however, there are a few major problems.
There are several different properties that may contain the value for the federal state or district. Sometimes it’s dbpprop:landkreis (the german word for district, in other cases it’s dbpedia-owl:district. Is it possible to combine those two in cases where only one of them is set?
Further, I’d like to read out the names of the cities in the north, northwest, …. Sometimes, these cities are referenced in dbpprop:north etc. The basic query for each direction is the same:
OPTIONAL {
?x dbpprop:north ?north
{ SELECT * WHERE {
?north rdfs:label ?northName
FILTER(lang(?northName) = "de")
}}
}
I really don’t want to repeat that eight times for every direction, is there any way to simplify this?
Sometimes, there are multiple other cities referenced (example). In those cases, there are multiple datasets returned. Is there any possibility to get a list of the names of those cities in a single dataset instead?
+---+---+---------------------------------------------------------------+
| x | … | southName |
+---+---+---------------------------------------------------------------+
| … | … | "Darmstadt"#de, "Stuttgart"#de, "Karlsruhe"#de, "Mannheim"#de |
+---+---+---------------------------------------------------------------+
Your feedback and your ideas are greatly appreciated!
Till
There are several different properties that may contain the value for the federal state or district. Sometimes it’s dbpprop:landkreis (the
german word for district, in other cases it’s dbpedia-owl:district. Is
it possible to combine those two in cases where only one of them is
set?
SPARQL property paths are great for this. You can just say
?subject dbprop:landkreis|dbpedia-owl:district ?district
If there are more properties, you'll probably prefer a version with values:
values ?districtProperty { dbprop:landkreis dbpedia-owl:district }
?subject ?districtProperty ?district
Further, I’d like to read out the names of the cities in the north,
northwest, …. Sometimes, these cities are referenced in dbpprop:north
etc. The basic query for each direction is the same:
OPTIONAL {
?x dbpprop:north ?north
{ SELECT * WHERE {
?north rdfs:label ?northName
FILTER(lang(?northName) = "de")
}}
}
Again, it's values to the rescue. Also, don't use lang(…) = … to filter languages, use langMatches:
optional {
values ?directionProp { dbpprop:north
#-- ...
dbpprop:south }
?subject ?directionProp ?direction
optional {
?direction rdfs:label ?directionLabel
filter langMatches(lang(?directionLabel),"de")
}
}
Sometimes, there are multiple other cities referenced (example). In
those cases, there are multiple datasets returned. Is there any
possibility to get a list of the names of those cities in a single
dataset instead?
+---+---+---------------------------------------------------------------+
| x | … | southName |
+---+---+---------------------------------------------------------------+
| … | … | "Darmstadt"#de, "Stuttgart"#de, "Karlsruhe"#de, "Mannheim"#de |
+---+---+---------------------------------------------------------------+
That's what group by and group_concat are for. See Aggregating results from SPARQL query. I don't actually see these results in the query you gave though, so I don't have good data to test a result with.
You also seem to be doing a lot of unnecessary subselects. You can just put additional triples in the graph pattern; you don't need a nested query to get additional information.
With those considerations, your query becomes:
select * where {
?x rdfs:label "Bentzin"#de ;
dbpedia-owl:postalCode ?zip ;
geo:lat ?lat ;
geo:long ?long
#-- district
optional {
?x dbpedia-owl:district|dbpprop:landkreis ?district .
?district rdfs:label ?districtName
filter langMatches(lang(?districtName),"de")
optional {
?district dbpprop:capital ?districtCapital .
?districtCapital rdfs:label ?districtCapitalName
filter langMatches(lang(?districtCapitalName),"de")
}
}
#federal state
optional {
?x dbpprop:bundesland|dbpedia-owl:federalState ?land .
?land rdfs:label ?landName
filter langMatches(lang(?landName),"de")
}
values ?directionProp { dbpprop:south dbpprop:north }
optional {
?x ?directionProp ?directionPlace .
?directionPlace rdfs:label ?directionName
filter langMatches(lang(?directionName),"de")
}
}
SPARQL results
Now, if you're just looking for the names of these things, without the associated URIs, you can actually use property paths to shorten a lot of the results that retrieve labels. E.g.:
select * where {
?x rdfs:label "Bentzin"#de ;
dbpedia-owl:postalCode ?zip ;
geo:lat ?lat ;
geo:long ?long
#-- district
optional {
?x (dbpedia-owl:district|dbpprop:landkreis)/rdfs:label ?districtName
filter langMatches(lang(?districtName),"de")
optional {
?district dbpprop:capital/rdfs:label ?districtCapitalName
filter langMatches(lang(?districtCapitalName),"de")
}
}
#-- federal state
optional {
?x (dbpprop:bundesland|dbpedia-owl:federalState)/rdfs:label ?landName
filter langMatches(lang(?landName),"de")
}
optional {
values ?directionProp { dbpprop:south dbpprop:north }
?x ?directionProp ?directionPlace .
?directionPlace rdfs:label ?directionName
filter langMatches(lang(?directionName),"de")
}
}
SPARQL results