This seems like it should be a simple/common thing, but I haven't found any useful answers that work.
I want to get a page of results (using OFFSET
and LIMIT
) as well as a COUNT
of total results in the same query, without repeating or re-running the query. In other words, I want to run the query once, count the results, get the first n results after some offset, and return just those n results along with the total result count. The exact format for how this is returned doesn't matter; I just need the data.
The closest answer I've found was in How to get total number of results when using LIMIT in SPARQL?, but the solution boils down to "duplicate the WHERE
clause in two subqueries", which seems unnecessary (and runs the query twice(?)).
I suspect this can be done with some combination of subqueries and possibly a UNION
, but I'm new to SPARQL so my grasp on its semantics isn't very firm yet.
A blatantly invalid example that illustrates what I want to accomplish (but not how I intend to do it):
SELECT (?id OFFSET 5 LIMIT 10 AS ?pageOfResults) (COUNT(?id) AS ?totalResults)
WHERE {
?id some:predicate some:object
ORDER BY ?id
}
The closest I've gotten is embodied by the next two examples. First, one which gives the desired result set (in this case, an extra result that contains the count). This is based on the link above. As noted above, it does so by duplicating the WHERE
clause (effectively running the same query twice unless I misunderstand how SPARQL works), which I want to avoid:
SELECT ?id ?count
WHERE {
{
SELECT (COUNT(*) as ?count)
WHERE {
?id some:predicate some:object .
}
}
UNION
{
SELECT ?id
WHERE {
?id some:predicate some:object .
}
ORDER BY ?id
OFFSET 5
LIMIT 10
}
}
Next, one which comes close to what I want, but which always returns a ?count
of 1 (presumably because it's counting the ?id
s being grouped instead of counting all of the matches). I was trying to get (and COUNT
) all of the matches first before passing the ?id
up to the outer layer to get OFFSET
and LIMIT
ed (and that part seems to work).
SELECT ?id ?count
{
{
SELECT ?id (COUNT(*) as ?count)
WHERE {
?id some:predicate some:object .
}
GROUP BY ?id
ORDER BY ?id
}
}
OFFSET 5
LIMIT 10
It would be nice (for this and other purposes) to be able to store the result of the WHERE
clause in a variable and then do two separate SELECT
s on it (one for the page of results, one for the count), but if that's possible, I haven't seen a way to do it.