Quick Optimization Reminders
Most AGS developers know these already, but here’s a quick refresher checklist:
✅ Use VALUES
instead of multiple FILTER
conditions
✅ Apply LIMIT
and OFFSET
for iterative testing
✅ Avoid unbound joins that cause Cartesian products
✅ Aggregate using subqueries to reduce load
These small optimizations help, but the biggest performance gain comes from modular query design using WITH clauses.
Why WITH Matters
Most developers already know basic optimizations — like using VALUES
instead of broad FILTER
s, limiting results during testing, and avoiding cross-product joins.
But for complex analytics, the biggest performance gain comes from reusing logic across subqueries.
That’s where the WITH clause helps:
- Define a subquery once.
- Reuse it multiple times.
- Keep your main query clean and faster to execute.
Basic Example - Reusing Subquery Results
Goal
Find all movies with ratings above 9.0, and label those above 9.2 as “All-Time Best.”
PREFIX ex: <http://example.org/movie/>
WITH {
SELECT ?m ?title ?rating
WHERE {
?m a ex:Movie ;
ex:title ?title ;
ex:rating ?rating .
FILTER(?rating > 9.0)
}
} AS %topRated
SELECT ?title ?category
WHERE {
{ INCLUDE %topRated BIND("Top Rated" AS ?category) }
UNION
{ INCLUDE %topRated FILTER(?rating > 9.2) BIND("All-Time Best" AS ?category) }
}
ORDER BY ?category
Result:
Title | Category |
---|
The Shawshank Redemption | Top Rated |
The Godfather | Top Rated |
The Dark Knight | Top Rated |
The Shawshank Redemption | All-Time Best |
✅ WITH
executes once and feeds multiple query blocks — simpler and faster.
Practical Multi-Stage Query (Nested WITH)
You can define multiple WITH blocks for staged data preparation — much like Common Table Expressions (CTEs) in SQL.
This pattern is powerful for analytics, where you compute metrics in stages.
Goal
Compute each director’s average rating, then show only those above 9.0.
PREFIX ex: <http://example.org/movie/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
WITH {
SELECT ?d (AVG(?rating) AS ?avgRating)
WHERE {
?m a ex:Movie ;
ex:rating ?rating ;
ex:director ?d .
}
GROUP BY ?d
} AS %directorAvg
WITH {
SELECT ?director ?avgRating
WHERE {
INCLUDE %directorAvg
?d foaf:name ?director .
FILTER(?avgRating > 9.0)
}
} AS %topDirectors
SELECT ?director ?avgRating
WHERE { INCLUDE %topDirectors }
ORDER BY DESC(?avgRating)
Result:
Director | Avg Rating |
---|
Frank Darabont | 9.3 |
Francis Ford Coppola | 9.2 |
Christopher Nolan | 8.9 |
Quentin Tarantino | 8.9 |
✅ Each WITH block handles one transformation step: averaging first, filtering second. This improves query readability and modularity — and AGS optimizes each block independently.
Syntax Variations
AGS supports two equivalent ways to invoke a WITH
clause.
Both are parsed into the same internal query structure — you can use whichever suits your workflow.
Bracket Notation
Uses curly braces { ... }
and an alias beginning with %
SELECT *
WITH {
SELECT DISTINCT * WHERE {
?s ?property ?o .
?s a ?class .
}
} AS %set
WHERE {
{
INCLUDE %set
# UNION 1 logic here
} UNION {
INCLUDE %set
# UNION 2 logic here
}
BIND(UUID() AS ?validationResult)
}
Parens Notation
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX iirds: <http://iirds.tekom.de/iirds#>
PREFIX iirds_core: <http://iirds.tekom.de/iirds-core-ont#>
WITH (
SELECT DISTINCT ?pv ?status
WHERE {
VALUES ?searchString {"HR05024137"}
?workorder isafun:svocExecutiveServiceEmployeeKey ?searchString ;
isafun:SVOCUserStatus ?status ;
iirds:relates-to-product ?pv .
}
) AS <urn://workorders>
SELECT DISTINCT ?title
WHERE {
{ QUERY <urn://workorders> }
BIND(STR(?topic) AS ?topicID)
# SERVICE or further logic here
}
Notes:
- Both bracket and parens notations achieve the same result.
%alias
+ INCLUDE
is often used in developer queries.<urn://alias>
+ QUERY
is common in programmatically generated queries or tools.- Internally, AGS parses both syntaxes identically.