Theory
FILTER drops bindings that fail a boolean test:
SELECT ?ninja ?age WHERE {
?ninja a :Ninja ; :age ?age .
FILTER(?age >= 18)
}
The operators you'll reach for most often inside FILTER(...):
| Operator | Does |
|---|---|
= / != | Equality / inequality on RDF terms |
< <= > >= | Numeric / date comparison |
&& / || | Boolean AND / OR |
regex(?s, "^foo") | Regex match on a string |
lang(?lit) = "en" | Match a language tag on a literal |
bound(?x) | Did this variable get a binding? (esp. OPTIONAL) |
Three professional details that trip people up
FILTERscope is the whole group{ }, not its position. AFILTERplaced anywhere inside a{ }applies to every binding the group produces — it is not a line that runs 'at that point'. Move it for readability, but it filters the same set.- Three-valued logic. Comparing an unbound or type-mismatched value yields an error, and a
FILTERwhose expression errors is treated as false — the row is dropped.FILTER(?age >= 18)silently removes anyone with no:age. Usebound(?age)orCOALESCEwhen that's not what you mean. FILTERcannot create bindings — only remove rows. To compute a new value, useBIND(expr AS ?v); to constrain to a fixed set, useVALUESorIN. Reaching forFILTERto 'set' a variable is a category error.
