Remove repeated SPARQL sub-query to compare against the average

Viewed 23

Here is a subquery that counts the number of subject for 10 values of the object from the triples of the form ?sbj pq:P1810 ?obj . The predicate pq:P1810 is used because it is available from wikidata, we could use ?person foaf:name ?name instead, but FOAF is not available in wikidata.

SELECT ?obj (COUNT(?sbj) AS ?num_sbj) WHERE {
    ?sbj pq:P1810 ?obj .
} GROUP BY ?obj LIMIT 10

I would like to select all ?obj, which have a higher ?num_sbj than the average. The working solution I came up with is this :

SELECT ?obj ?num_sbj ?avg_num_sbj WHERE {
    {
        SELECT ?obj (COUNT(?sbj) AS ?num_sbj) WHERE {
            ?sbj pq:P1810 ?obj .
        } GROUP BY ?obj LIMIT 10
    }
    {
        SELECT (AVG(?num_sbj_) AS ?avg_num_sbj) WHERE {
            {
                SELECT ?obj_ (COUNT(?sbj_) AS ?num_sbj_) WHERE {
                    ?sjb_ pq:P1810 ?obj_ .
                } GROUP BY ?obj_ LIMIT 10
            }
        }
    }
    FILTER (?num_sbj > ?avg_num_sbj)
}

Here is a link to a running example in wikidata https://w.wiki/5Ci7

Unfortunately, the first sub-query has to be repeated in the second sub-query to fetch the average.

Is the subquery actually performed more than once? I feel like a query optimizer could see that the queries are the same and perform the reduction on a copy of the data, but I'm not sure whether this optimization would always be present.

Is it possible to reformulate the working solution such that no subquery is written more than once ?

0 Answers
Related