Reputation: 685
I am trying to write an elegant SPARQL that gives me one solution for multiple possible queries. I have a number of subjects and a number of predicates and I want to receive a single object. The existence of a single solution is very uncertain so I give multiple options. If I am not mistaken, this can be done with the following query:
SELECT ?object
WHERE {
:subjA|:subjB|:subjC :propA|:propB|:propC ?object.
}
LIMIT 1
The real problem is that I do not want any solution. I want order by :subjA
and then :propA
. To make it clear; I want the first solution in the following list of combinations:
:subjA
:propA
:subjA
:propB
:subjA
:propC
:subjB
:propA
:subjB
:propB
:subjB
:propC
:subjC
:propA
:subjC
:propB
:subjC
:propC
How to rewrite my query to get the first possible solution?
Upvotes: 3
Views: 123
Reputation: 8465
This is for sure not a valid SPARQL query. You can only use |
for the predicate which will then be called a property path but you're losing the variable binding.
SPARQL returns a set of rows but you can use for example the lexicographical order. Not sure, if this is what you want:
@prefix : <http://ex.org/> .
:subjA :propA :o1 .
:subjA :propC :o1 .
:subjB :propB :o1 .
:subjC :propB :o1 .
:subjC :propA :o1 .
:subjA :propC :o2 .
:subjB :propB :o2 .
:subjB :propC :o2 .
PREFIX : <http://ex.org/>
SELECT ?s ?p ?o
WHERE
{ VALUES ?s { :subjA :subjB :subjC }
VALUES ?p { :propA :propB :propC }
?s ?p ?o
}
ORDER BY ?s ?p
-------------------------
| s | p | o |
=========================
| :subjA | :propA | :o1 |
| :subjA | :propC | :o1 |
| :subjA | :propC | :o2 |
| :subjB | :propB | :o1 |
| :subjB | :propB | :o2 |
| :subjB | :propC | :o2 |
| :subjC | :propA | :o1 |
| :subjC | :propB | :o1 |
-------------------------
Since a used-defined order is wanted, as a workaround an index for entities can be used (I changed the order of :subjB
and :subjC
resp. :propB
and :propC
to show the difference compared to lexicographical order):
PREFIX : <http://ex.org/>
SELECT ?s ?p ?o
WHERE
{ VALUES (?sid ?s) { (1 :subjA) (2 :subjC) (3 :subjB) }
VALUES (?pid ?p) { (1 :propA) (2 :propC) (3 :propB) }
?s ?p ?o
}
ORDER BY ?sid ?pid
-------------------------
| s | p | o |
=========================
| :subjA | :propA | :o1 |
| :subjA | :propC | :o1 |
| :subjA | :propC | :o2 |
| :subjC | :propB | :o1 |
| :subjC | :propA | :o1 |
| :subjB | :propB | :o1 |
| :subjB | :propB | :o2 |
| :subjB | :propC | :o2 |
-------------------------
Upvotes: 4
Reputation: 327
You can do it by two ways. They are different by your needs to alphabetic sort or not. First for alphabetic sort:
Select ?object where {
{Select (min(?sub) as ?msub) where {
?sub :propA|:propB|:propC ?obj1
Filter ( ?sub = :subjA or :sub=?...)
} .
{Select (min(?prop) as ?mrop_by_msub) where {
?msub ?prop ?obj2
Filter ( ?prop = :propA or ?prop=?...)
} .
?msub ?mrop_by_msub ?object
}
Limit 1
Second way for custom sort:
Select ?object where {
{:subjA :propA ?object}
Union
{:subjA :propB ?object}
.......
} limit 1
I write all of it by my memory, so there is may be some errors in this code.
Add third way: You can add to your rdf store something like this:
:subjA :order_num 1
:subjB :order_num 2
:subjC :order_num 3
:propA :order_num 1
:propB :order_num 2
:propC :order_num 3
And then use query like this:
select ?object where{
?sub :order_num ?ord_num_sub .
?prop :order_num ?ord_num_prop .
?sub ?prop ?object
} order by ?ord_num_sub ?ord_num_prop
limit 1
or if you want to use different of subjs and props you can add filter: filter ( (?ord_num_sub=2 or ?ord_num_sub=3) and (?ord_num_prop=1 or ?ord_num_prop=2) )
Upvotes: 1