← every query · class 09 · queries/q4-customers-by-category-last-month.rq
Q4 · Which customers ordered peripherals last month?
The same answer in both regimes: this query asks only for what was written.
| ?customer | ?customerName | ?country | ?date |
|---|---|---|---|
| customer:4 | "Papelaria Central" | — | "2026-10-12"^^xsd:date |
The query
# Q4. Which customers ordered products of category X last month?
# X = category:peripherals. "Last month" is October 2026: the reference date is
# written into the query so that the result is reproducible. In a service one
# would use NOW() and a relative interval.
PREFIX schema: <https://schema.org/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX onto: <https://data.csoares.me/onto#>
PREFIX category: <https://data.csoares.me/category/>
# DISTINCT: a customer with two matching orders would otherwise appear twice
SELECT DISTINCT ?customer ?customerName ?country ?date
WHERE {
?order a onto:Order ;
onto:hasCustomer ?customer ;
onto:date ?date ;
onto:containsProduct ?p .
?p schema:category category:peripherals .
?customer schema:name ?customerName .
# The customers in this graph have no country yet. In an OPTIONAL that only
# leaves ?country empty; as a plain pattern it would remove every row.
OPTIONAL { ?customer onto:country ?country }
# a typed literal: "..."^^xsd:date compares as a date, not as text
FILTER (?date >= "2026-10-01"^^xsd:date && ?date < "2026-11-01"^^xsd:date)
}
ORDER BY ?customerName