2

I have a query that returns several columns, i.e.:

SELECT ?a ?b ?c
WHERE { ... }

Every column variable is an IRI. Obviously this returns a unique row for every combination of column values (note that values may not be unique to a column):

<urn:id:x:1> <urn:id:a:2> <urn:id:j:3>
<urn:id:x:1> <urn:id:a:2> <urn:id:j:4>
<urn:id:x:1> <urn:id:j:4> <urn:id:k:5>
<urn:id:y:2> <urn:id:j:4> <urn:id:k:6>
...

However, all I need are the unique IRIs spanning all rows and columns. i.e.:

<urn:id:x:1>
<urn:id:a:2>
<urn:id:j:3>
<urn:id:j:4>
<urn:id:k:5>
<urn:id:y:2>
<urn:id:k:6>
...

Is it possible to achieve this using SPARQL, or do I need to post-process the results to merge and de-deduplicate the values? Order is unimportant.

wst
  • 11,681
  • 1
  • 24
  • 39
  • 1
    the most simple but clearly most expensive (depending on the query optimizer) way would be to wrap the graph pattern in subqueries per each column and use the `UNION` of those. Something like `SELECT DISTINCT ?x { {select ?x { ?x ?p ?o } } UNION {select ?x { ?s ?x ?o } } UNION { select ?x {?s ?p ?x }} }` - well I think you get the idea? And as I said, might have poor performance and there might be other ways - was just the first and most trivial option that came into my mind – UninformedUser May 24 '19 at 05:17

1 Answers1

3
SELECT DISTINCT ?d {
    ...
    VALUES ?i { 1 2 3 }
    BIND (if(?i=1, ?a, if(?i=2, ?b, ?c)) AS ?d)
}

What does this do?

  1. The VALUES clause creates three copies of each solution and numbers them with a variable ?i
  2. The BIND clause creates a new variable ?d whose value is ?a, ?b or ?c, depending on whether ?i is 1, 2 or 3 in the given solution
  3. The SELECT DISTINCT ?d returns only ?d and removes duplicates
cygri
  • 9,412
  • 1
  • 25
  • 47
  • I'm still trying to understand the semantics of this. You can only assign a variable to be a sequence of arbitrary values through `VALUES`, but variables are invalid within `VALUES`, so the only way to generate a sequence from variables is through a 2-step join via `BIND` using an `IF` expression like this? – wst May 24 '19 at 19:53
  • 1
    Correct. At least it’s the only way I could think of that doesn’t involve triplicating the whole query pattern. – cygri May 24 '19 at 20:33