3

This works:

SELECT ?propLabel ?val WHERE {
    BIND("incoming"@en AS ?propLabel)
    {
      SELECT (COUNT(?s) AS ?val) WHERE {
        ?s ?p wd:Q8740.
        _:b72 wikibase:directClaim ?p.
      }
    }
}

But this does not, I assume because the sub-query is evaluated first, and therefore ?entity is not bound yet:

SELECT ?propLabel ?val WHERE {
  BIND(wd:Q8740 as ?entity)
    BIND("incoming"@en AS ?propLabel)
    {
      SELECT (COUNT(?s) AS ?val) WHERE {
        ?s ?p ?entity.
        _:b72 wikibase:directClaim ?p.
      }
    }
}

If so, how do we "pass" a variable into a subquery?

T3db0t
  • 3,491
  • 4
  • 28
  • 45
  • 1
    that's not how subqueries work. it's bottom up evaluation. what prevents you from using the URI directly in the subquery? I don't get the problem – UninformedUser Oct 31 '18 at 19:30
  • 1
    @AKSW This is a small section of a large query that contains a large number of places where the subject is required. As I test the query in the Wikidata query editor, it'd be insane to manually replace every instance of the subject, so it's much more feasible to use a variable to hold the subject. – T3db0t Oct 31 '18 at 19:59
  • 1
    I think what you're aiming for is a parameterized SPARQL query, which I do not believe can be done with pure SPARQL. Different tools (such as Jena, or Virtuoso's SPASQL a/k/a SPARQL-in-SQL) provide different ways to do such parameterization outside SPARQL. – TallTed Oct 31 '18 at 21:30
  • [Try it](https://query.wikidata.org/#SELECT%20%3FpropLabel%20%3Fval%20WHERE%20%7B%0A%20%20BIND%20%28wd%3AQ8740%20AS%20%3Fentity%29%0A%20%20BIND%28%22incoming%22%40en%20AS%20%3FpropLabel%29%0A%20%20%7B%20%0A%20%20%20%20SELECT%20%28COUNT%28%3Fs%29%20AS%20%3Fval%29%20%3Fentity%20WHERE%20%7B%0A%20%20%20%20%20%20%3Fs%20%3Fp%20%3Fentity.%0A%20%20%20%20%20%20%5B%5D%20wikibase%3AdirectClaim%20%3Fp.%0A%20%20%20%20%7D%20GROUP%20BY%20%3Fentity%0A%20%20%7D%20%0A%7D). In that particular case, optimizer works well. – Stanislav Kralin Oct 31 '18 at 22:41
  • Yeah; I can do the templating in my script, but I just wanted to see if there was some "official" way to do it :) – T3db0t Nov 01 '18 at 14:57

1 Answers1

3

Read the Optimizations in Blazegraph section in the SPARQL Bottom Up Semantics article, then help the optimizer slightly:

SELECT ?propLabel ?val WHERE {
  BIND (wd:Q8740 AS ?entity)
  BIND("incoming"@en AS ?propLabel)
  { 
    SELECT (COUNT(?s) AS ?val) ?entity WHERE {
      ?s ?p ?entity .
      [] wikibase:directClaim ?p 
    } GROUP BY ?entity
  } 
}

Try it!

Just add the ?entity variable to the projection (and then you should GROUP BY ?entity explicitely).
As a result, you will have additional joinVars=[entity] in the query plan.

It's interesting that such optimization can not be disabled using hint:Query hint:optimizer "None".

Stanislav Kralin
  • 11,070
  • 4
  • 35
  • 58
  • Interesting, thank you; I don't understand this yet but it gives me something to chew on ;) – T3db0t Nov 01 '18 at 15:11
  • In short, don't care. Blazegraph optimizer do its job almost every time when it is possible, except for hard cases like aggregates etc, when it needs some help. – Stanislav Kralin Nov 01 '18 at 17:56