I am wondering how group patterns are evaluated in SPARQL. My assumption was that each group pattern is evaluated separately, then solution bindings from groups are joined together. However, it seems not to be the case.
Let's take this example data:
:film1 :hasDirector :director1.
Let's have this example following query:
select * where {
{?a :hasDirector ?c.}
{optional {?c :fromCountry ?e}}.
}
I would assume that each group will be evaluated separately and then results from both groups will be joined. in terms of relational algebra, it would look like first_group INNER-JOIN second_group
. However, it's not the case...
Evaluating each group separately; the first group pattern yeilds the solution: ?a = :film1, ?c = :director1
. The second triple pattern does not yield any solution
. Now if my assumption were correct, joining results wouldn't return any solution. However, this query returns one solution with ?a = :film1 ,?c = :director1, ?e unbound
.
This result is the same as if there were no groups used {}
, also the same as if the following query was executed:
select * where {
?a :hasDirector ?c.
optional {?c :fromCountry ?e}.
}
The last query (relationally again to facilitate understanding) first_group LEFT-OUTER-JOIN second_group
.
How group patterns are evaluated in SPARQL? What am I missng here?
PS. I am using GraphDB for testing...
EDIT1:
Now trying to get algebra of queries via Jena ARQ... seems to confirm what I expected?
This is what I get from Jena ARQ for the first query algebra:
(join
(bgp (triple ?a <http://www.example.com/hasDirector> ?c))
(leftjoin
(table unit)
(bgp (triple ?c <http://www.example.com/fromCountry> ?e))))
Second query:
(leftjoin
(bgp (triple ?a <http://www.example.com/hasDirector> ?c))
(bgp (triple ?c <http://www.example.com/fromCountry> ?e)))
EDIT2:
Jena gives the same results of GraphDB for the first query though algebra looks as I just showed.
EDIT3:
Could this be the reason? treatment of unbound values (as pre null in relational DB) in joins is quite strange. See Appendix C here.
EDIT4:
Seems the problem is as mentioned in EDIT3 adding FILTER (BOUND (?c))
in the first query will give the expected results!
select * where {
{?a :hasDirector ?c.}
{optional {?c :fromCountry ?e} FILTER (BOUND (?c))}.
}
But now again... What should the default behaviour be when two consequent group patterns happen? joiing them? disregarding this unbound (null) issue.