onexpeters
onexpeters

Reputation: 141

combining SPARQL queries

I want to fetch the population of the most and least populated state. I know how to use ORDER BY (ASC and DESC). How can I combine these two (ASC and DESC) in a single query?

SELECT  ?population
{
?state rdf:type :State
?state :hasPopulation ?population.
} ORDER BY DESC(?population) LIMIT 1
AND

SELECT  ?population
{
?state rdf:type :State
?state :hasPopulation ?population.
} ORDER BY ASC(?population) LIMIT 1

Upvotes: 1

Views: 1042

Answers (2)

SPARQL User
SPARQL User

Reputation: 1

You could perhaps use UNION to combine 'max' and 'min' population. Here is AnzoGraph syntax:

    WITH (
      SELECT ?pop 
      WHERE { 
          ?state a :State ; 
                 :hasPopulation ?pop
      }
      as <unsorted_pop>
   )
   SELECT *
    WHERE {
        { SELECT (max(?pop) as ?population)
          WHERE { QUERY <unsorted_pop> }
        }
        UNION
        { SELECT (min(?pop) as ?population)
          WHERE { QUERY <unsorted_pop> }
        }
    }

Upvotes: 0

Stanislav Kralin
Stanislav Kralin

Reputation: 11459

SELECT ?population_max ?population_min {
    ?state_max rdf:type :State .
    ?state_max :hasPopulation ?population_max .
    ?state_min rdf:type :State .
    ?state_min :hasPopulation ?population_min .
} ORDER BY DESC(?population_max) ASC(?population_min) LIMIT 1

Perhaps more efficient:

SELECT * {
    {
        SELECT (?population AS ?population_max) {
            ?state rdf:type :State .
            ?state :hasPopulation ?population .
        } ORDER BY DESC(?population) LIMIT 1 
    }
    {
        SELECT (?population AS ?population_min) {
            ?state rdf:type :State .
            ?state :hasPopulation ?population .
        } ORDER BY ASC(?population) LIMIT 1
    }
}

With AnzoGraph or Blazegraph, one could use named subqueries in such a case:

SELECT *
WITH {
    SELECT ?pop { [] a :State ; :hasPopulation ?pop }
} AS %unsorted
WHERE {
    { SELECT (?pop AS ?max) { INCLUDE %unsorted } ORDER BY DESC(?pop) LIMIT 1 }
    { SELECT (?pop AS ?min) { INCLUDE %unsorted } ORDER BY  ASC(?pop) LIMIT 1 }
}

Finally, rather rewriting than combining:

SELECT (MAX(?population) AS ?population_max) (MIN(?population) AS ?population_min) {
    ?state rdf:type :State .
    ?state :hasPopulation ?population
} 

If aggregates are used... but the GROUP BY term is not used, then this is taken to be a single implicit group, to which all solutions belong.

Upvotes: 5

Related Questions