3

my problem is very simple: I have a source my:g1 that contains:

my:a1 my:b "literal 1"

Then I have a second source my:g2 that contains:

my:a2 my:b my:c.
my:c rdfs:label "literal 2"

how can I set a SPARQL query that produces something like:

| ?a    | ?b    | ?literal    |
|-------|-------|-------------|
| my:a1 | my:b  | "literal 1" |
| my:a2 | my:b  | "literal 2" |

ie. how can i tell sparql to use the same variable for both "literal 1" and "literal 2": I'm looking for something like

Select ?a ?b ?literal 
where {
 if (?g = my:g1) then
  GRAPH ?g { ?a ?b ?literal}
 else if (?g = my:g2) then
  GRAPH ?g { ?a ?b ?c. ?c rdfs:label ?literal}
}

NOTE: I know that this query is horribly wrong, but is just to clarify my intention

EDIT:

in this specific case a "union" statement like

select ?a ?b ?literal 
where {
{
 GRAPH my:g1 { ?a ?b ?literal}
}
union
{
  GRAPH my:g2 { ?a ?b ?c. ?c rdfs:label ?literal}
}
}

would work, but is not my "real" case. There are any other solutions?

ffa
  • 747
  • 1
  • 6
  • 14

1 Answers1

2

You can use a property path and a filter. The trick here is that the property path with a question mark means a path of length 0 or 1. If the path is of length 0, then ?literal is the same as ?c, which covers the case when ?a is related directly to a literal. If the path is length 1, then ?literal is the value of rdfs:label for ?c.

Here's an example with real data:

@prefix : <urn:ex:>

:a :b "literal 1" .
:a :b :c .
:c :label "literal 2" .prefix : <urn:ex:>
select distinct ?a ?b ?literal where {
  ?a ?b ?c .
  ?c :label? ?literal
  filter isLiteral(?literal)
}
-----------------------------
| a  | b      | literal     |
=============================
| :a | :b     | "literal 1" |
| :a | :b     | "literal 2" |
| :c | :label | "literal 2" |
-----------------------------

You might not have been expecting that last row in the results, but if ?a and ?b are variables, then it makes sense, because there's nothing saying that the variable ?b has to be bound to the specific property :b.

Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
  • Your answer is really useful but I can't figure out how to make it work against 2 different graphs. Any ideas? – ffa May 15 '15 at 16:23
  • what do you mean "work against two different graphs"? Do you mean that in one graph, the values are literals, and in the other, the values are resources with an rdfs:label property? Even if that's the case, you should be able to just wrap the whole thing. E.g., `select ... where { graph ?g { ?a ?b ?c . ... filter ... } }`. – Joshua Taylor May 15 '15 at 16:26
  • It's quite unclear what your graph context is from the question. In the first example, you use `graph ?g { ... }` with a variable, but then in the second you use a union, but URIs for the graphs: `{ graph my:g1 { ... } } union { graph my:g2 { ... } }`. – Joshua Taylor May 15 '15 at 16:27