Claude-skill-registry lang-sparql-dev
Foundational SPARQL patterns covering RDF querying, triple patterns, graph patterns, and semantic web fundamentals. Use when querying RDF data or working with knowledge graphs. This is the entry point for SPARQL development.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/lang-sparql-dev" ~/.claude/skills/majiayu000-claude-skill-registry-lang-sparql-dev && rm -rf "$T"
skills/data/lang-sparql-dev/SKILL.mdSPARQL Development Skill
Comprehensive foundational patterns for SPARQL (SPARQL Protocol and RDF Query Language), covering RDF fundamentals, query patterns, graph operations, and semantic web development.
Table of Contents
- RDF Fundamentals
- Basic Query Patterns
- Graph Patterns
- Query Forms
- Solution Modifiers
- Aggregations and Grouping
- Property Paths
- Federated Queries
- Common Ontologies
- Best Practices
RDF Fundamentals
Triple Structure
RDF data is represented as triples: Subject-Predicate-Object.
# Basic triple pattern <http://example.org/person/Alice> <http://xmlns.com/foaf/0.1/name> "Alice Smith" . # Compact notation with prefixes PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX ex: <http://example.org/> ex:person/Alice foaf:name "Alice Smith" .
URI Types
# Full URI <http://example.org/resource/123> # Prefixed name PREFIX ex: <http://example.org/> ex:resource/123 # Blank nodes (anonymous resources) _:node1 [] # Literals "Plain string" "String with language"@en "42"^^xsd:integer "2024-01-15"^^xsd:date
Literal Types
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> # String literals "Simple string" "String with language"@en "Multi-line string" # Numeric literals 42 3.14 "100"^^xsd:integer "99.99"^^xsd:decimal # Boolean literals true false "true"^^xsd:boolean # Date/Time literals "2024-01-15"^^xsd:date "14:30:00"^^xsd:time "2024-01-15T14:30:00Z"^^xsd:dateTime # Other common types "http://example.org"^^xsd:anyURI "PT1H30M"^^xsd:duration
RDF Graphs
# Default graph (unnamed) SELECT * WHERE { ?s ?p ?o . } # Named graphs SELECT * WHERE { GRAPH <http://example.org/graph1> { ?s ?p ?o . } } # Query across multiple graphs SELECT * WHERE { { GRAPH <http://example.org/graph1> { ?s ?p ?o . } } UNION { GRAPH <http://example.org/graph2> { ?s ?p ?o . } } } # Query from all graphs SELECT * WHERE { GRAPH ?g { ?s ?p ?o . } }
RDF Collections
# RDF Lists (linked list structure) PREFIX ex: <http://example.org/> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> ex:myList rdf:first "Item 1" ; rdf:rest [ rdf:first "Item 2" ; rdf:rest [ rdf:first "Item 3" ; rdf:rest rdf:nil ] ] . # Shorthand syntax ex:myList rdf:value ( "Item 1" "Item 2" "Item 3" ) . # Querying lists SELECT ?item WHERE { ?list rdf:rest*/rdf:first ?item . }
Basic Query Patterns
SELECT Queries
PREFIX foaf: <http://xmlns.com/foaf/0.1/> # Basic SELECT SELECT ?name WHERE { ?person foaf:name ?name . } # Multiple variables SELECT ?person ?name ?email WHERE { ?person foaf:name ?name ; foaf:mbox ?email . } # SELECT DISTINCT (remove duplicates) SELECT DISTINCT ?type WHERE { ?s a ?type . } # SELECT * (all variables) SELECT * WHERE { ?s ?p ?o . } # SELECT with expressions SELECT ?person ?age (?age + 10 AS ?ageIn10Years) WHERE { ?person foaf:age ?age . }
WHERE Clause Patterns
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX ex: <http://example.org/> # Basic triple pattern SELECT ?name WHERE { ex:Alice foaf:name ?name . } # Multiple triple patterns (implicit AND) SELECT ?name ?email WHERE { ?person foaf:name ?name . ?person foaf:mbox ?email . } # Shorthand for same subject (semicolon) SELECT ?name ?email WHERE { ?person foaf:name ?name ; foaf:mbox ?email . } # Shorthand for same subject and predicate (comma) SELECT ?person ?friend WHERE { ?person foaf:name "Alice" ; foaf:knows ?friend1, ?friend2 . } # Nested patterns SELECT ?person ?friendName WHERE { ?person foaf:name "Alice" . ?person foaf:knows ?friend . ?friend foaf:name ?friendName . }
Filtering Results
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> # String filtering SELECT ?person ?name WHERE { ?person foaf:name ?name . FILTER (regex(?name, "Smith", "i")) # Case-insensitive } # Numeric filtering SELECT ?person ?age WHERE { ?person foaf:age ?age . FILTER (?age >= 18 && ?age < 65) } # Type checking SELECT ?person ?value WHERE { ?person foaf:name ?value . FILTER (isLiteral(?value)) } # Language filtering SELECT ?label WHERE { ?resource rdfs:label ?label . FILTER (lang(?label) = "en") } # Negation SELECT ?person ?name WHERE { ?person foaf:name ?name . FILTER (!bound(?person)) # Where variable is not bound } # String functions in FILTER SELECT ?name WHERE { ?person foaf:name ?name . FILTER ( strlen(?name) > 5 && contains(?name, "Smith") && strstarts(?name, "J") ) } # Date filtering SELECT ?event ?date WHERE { ?event ex:eventDate ?date . FILTER ( ?date >= "2024-01-01"^^xsd:date && ?date < "2025-01-01"^^xsd:date ) } # Multiple conditions SELECT ?person WHERE { ?person foaf:age ?age ; foaf:name ?name . FILTER ( (?age > 18 && ?age < 65) || (regex(?name, "^Admin")) ) }
Binding Values
PREFIX foaf: <http://xmlns.com/foaf/0.1/> # BIND - assign values to variables SELECT ?person ?name ?greeting WHERE { ?person foaf:name ?name . BIND (CONCAT("Hello, ", ?name) AS ?greeting) } # Multiple BIND statements SELECT ?x ?squared ?cubed WHERE { VALUES ?x { 1 2 3 4 5 } BIND (?x * ?x AS ?squared) BIND (?x * ?x * ?x AS ?cubed) } # BIND with conditionals SELECT ?person ?ageGroup WHERE { ?person foaf:age ?age . BIND ( IF(?age < 18, "Minor", IF(?age < 65, "Adult", "Senior")) AS ?ageGroup ) } # COALESCE - first non-null value SELECT ?person ?contact WHERE { ?person foaf:mbox ?email . OPTIONAL { ?person foaf:phone ?phone } BIND (COALESCE(?phone, ?email) AS ?contact) }
VALUES Clause
PREFIX ex: <http://example.org/> # Inline data SELECT ?person ?name WHERE { ?person ex:name ?name . VALUES ?person { ex:Alice ex:Bob ex:Charlie } } # Multiple variables SELECT ?person ?age WHERE { VALUES (?person ?age) { (ex:Alice 30) (ex:Bob 25) (ex:Charlie 35) } ?person ex:name ?name . } # Mixing bound and unbound values SELECT ?x ?y WHERE { VALUES (?x ?y) { (1 UNDEF) (2 3) (UNDEF 4) } }
Graph Patterns
OPTIONAL Patterns
PREFIX foaf: <http://xmlns.com/foaf/0.1/> # Basic OPTIONAL SELECT ?person ?name ?email WHERE { ?person foaf:name ?name . OPTIONAL { ?person foaf:mbox ?email } } # Multiple OPTIONAL blocks SELECT ?person ?name ?email ?phone WHERE { ?person foaf:name ?name . OPTIONAL { ?person foaf:mbox ?email } OPTIONAL { ?person foaf:phone ?phone } } # Nested OPTIONAL SELECT ?person ?friend ?friendEmail WHERE { ?person foaf:name "Alice" . OPTIONAL { ?person foaf:knows ?friend . OPTIONAL { ?friend foaf:mbox ?friendEmail } } } # OPTIONAL with FILTER SELECT ?person ?name ?age WHERE { ?person foaf:name ?name . OPTIONAL { ?person foaf:age ?age . FILTER (?age >= 18) } }
UNION Patterns
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX vcard: <http://www.w3.org/2006/vcard/ns#> # Basic UNION SELECT ?name WHERE { { ?person foaf:name ?name . } UNION { ?person vcard:fn ?name . } } # Multiple UNIONs SELECT ?contact WHERE { { ?person foaf:mbox ?contact . } UNION { ?person foaf:phone ?contact . } UNION { ?person vcard:email ?contact . } } # UNION with different patterns SELECT ?person ?label WHERE { { ?person foaf:name ?label . ?person foaf:age ?age . FILTER (?age > 18) } UNION { ?person rdfs:label ?label . ?person a foaf:Organization . } }
MINUS Patterns
PREFIX foaf: <http://xmlns.com/foaf/0.1/> # Exclude patterns SELECT ?person ?name WHERE { ?person foaf:name ?name . MINUS { ?person foaf:mbox ?email . } } # Multiple MINUS SELECT ?person WHERE { ?person a foaf:Person . MINUS { ?person foaf:age ?age } MINUS { ?person foaf:mbox ?email } } # MINUS vs OPTIONAL + FILTER NOT EXISTS # These are similar but have subtle differences SELECT ?person ?name WHERE { ?person foaf:name ?name . FILTER NOT EXISTS { ?person foaf:mbox ?email . } }
NOT EXISTS Patterns
PREFIX foaf: <http://xmlns.com/foaf/0.1/> # Basic negation SELECT ?person WHERE { ?person a foaf:Person . FILTER NOT EXISTS { ?person foaf:knows ?other . } } # Complex negation SELECT ?person WHERE { ?person foaf:name ?name . FILTER NOT EXISTS { ?person foaf:knows ?friend . ?friend foaf:mbox ?email . } } # Combination with EXISTS SELECT ?person WHERE { ?person a foaf:Person . FILTER EXISTS { ?person foaf:name ?name } FILTER NOT EXISTS { ?person foaf:mbox ?email } }
Graph Patterns
PREFIX ex: <http://example.org/> # Query specific named graph SELECT ?s ?p ?o WHERE { GRAPH ex:graph1 { ?s ?p ?o . } } # Query variable graph SELECT ?g ?s ?p WHERE { GRAPH ?g { ?s ?p ?o . } } # Combine default and named graphs SELECT ?person ?name WHERE { # From default graph ?person a foaf:Person . # From named graph GRAPH ex:privateData { ?person foaf:name ?name . } } # Multiple graphs with UNION SELECT ?s ?p ?o WHERE { { GRAPH ex:graph1 { ?s ?p ?o } } UNION { GRAPH ex:graph2 { ?s ?p ?o } } }
Subqueries
PREFIX foaf: <http://xmlns.com/foaf/0.1/> # Basic subquery SELECT ?person ?friendCount WHERE { ?person a foaf:Person . { SELECT ?person (COUNT(?friend) AS ?friendCount) WHERE { ?person foaf:knows ?friend . } GROUP BY ?person } } # Nested subqueries SELECT ?person ?name ?avgFriendAge WHERE { ?person foaf:name ?name . { SELECT ?person (AVG(?friendAge) AS ?avgFriendAge) WHERE { ?person foaf:knows ?friend . ?friend foaf:age ?friendAge . } GROUP BY ?person } } # Subquery with LIMIT SELECT ?person ?topFriend WHERE { ?person foaf:name ?name . { SELECT ?person ?topFriend WHERE { ?person foaf:knows ?topFriend . ?topFriend foaf:popularityScore ?score . } ORDER BY DESC(?score) LIMIT 1 } }
Query Forms
CONSTRUCT Queries
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX vcard: <http://www.w3.org/2006/vcard/ns#> # Basic CONSTRUCT - transform data CONSTRUCT { ?person vcard:fn ?name . ?person vcard:email ?email . } WHERE { ?person foaf:name ?name . OPTIONAL { ?person foaf:mbox ?email } } # CONSTRUCT with calculated values CONSTRUCT { ?person ex:fullInfo ?info . } WHERE { ?person foaf:name ?name ; foaf:age ?age . BIND (CONCAT(?name, " (", STR(?age), ")") AS ?info) } # CONSTRUCT with conditional patterns CONSTRUCT { ?person a ex:Adult . } WHERE { ?person foaf:age ?age . FILTER (?age >= 18) } # CONSTRUCT with multiple patterns CONSTRUCT { ?person a ex:SocialPerson ; ex:friendCount ?count ; ex:hasFriend ?friend . } WHERE { ?person foaf:knows ?friend . { SELECT ?person (COUNT(?f) AS ?count) WHERE { ?person foaf:knows ?f . } GROUP BY ?person } } # Empty CONSTRUCT template (copy all matching triples) CONSTRUCT WHERE { ?s ?p ?o . FILTER (?p = foaf:knows) }
DESCRIBE Queries
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX ex: <http://example.org/> # DESCRIBE specific resource DESCRIBE ex:Alice # DESCRIBE with variables DESCRIBE ?person WHERE { ?person foaf:name "Alice Smith" . } # DESCRIBE multiple resources DESCRIBE ex:Alice ex:Bob ex:Charlie # DESCRIBE with pattern DESCRIBE ?person ?friend WHERE { ?person foaf:name "Alice" . ?person foaf:knows ?friend . } # DESCRIBE all resources of a type DESCRIBE ?person WHERE { ?person a foaf:Person . } LIMIT 10
ASK Queries
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX ex: <http://example.org/> # Basic ASK - check existence ASK { ex:Alice foaf:knows ex:Bob . } # ASK with complex pattern ASK { ?person foaf:name "Alice" ; foaf:age ?age . FILTER (?age >= 18) } # ASK with OPTIONAL ASK { ex:Alice foaf:name ?name . OPTIONAL { ex:Alice foaf:mbox ?email } } # ASK with negation ASK { ex:Alice a foaf:Person . FILTER NOT EXISTS { ex:Alice foaf:mbox ?email . } }
Solution Modifiers
ORDER BY
PREFIX foaf: <http://xmlns.com/foaf/0.1/> # Ascending order (default) SELECT ?person ?age WHERE { ?person foaf:age ?age . } ORDER BY ?age # Descending order SELECT ?person ?age WHERE { ?person foaf:age ?age . } ORDER BY DESC(?age) # Multiple sort keys SELECT ?person ?lastName ?firstName WHERE { ?person foaf:lastName ?lastName ; foaf:firstName ?firstName . } ORDER BY ?lastName ?firstName # Mixed sort directions SELECT ?person ?age ?name WHERE { ?person foaf:age ?age ; foaf:name ?name . } ORDER BY DESC(?age) ASC(?name) # ORDER BY with expressions SELECT ?person ?name ?age WHERE { ?person foaf:name ?name ; foaf:age ?age . } ORDER BY (strlen(?name)) DESC(?age)
LIMIT and OFFSET
PREFIX foaf: <http://xmlns.com/foaf/0.1/> # LIMIT - restrict number of results SELECT ?person ?name WHERE { ?person foaf:name ?name . } LIMIT 10 # OFFSET - skip first N results SELECT ?person ?name WHERE { ?person foaf:name ?name . } OFFSET 20 # Pagination with LIMIT and OFFSET SELECT ?person ?name WHERE { ?person foaf:name ?name . } ORDER BY ?name LIMIT 10 OFFSET 20 # Page 3 (skip first 20, show next 10) # LIMIT with ORDER BY SELECT ?person ?age WHERE { ?person foaf:age ?age . } ORDER BY DESC(?age) LIMIT 5 # Top 5 oldest people
DISTINCT and REDUCED
PREFIX foaf: <http://xmlns.com/foaf/0.1/> # DISTINCT - remove duplicates SELECT DISTINCT ?type WHERE { ?s a ?type . } # REDUCED - allow duplicates but permit elimination # (useful for performance optimization) SELECT REDUCED ?type WHERE { ?s a ?type . } # DISTINCT with multiple variables SELECT DISTINCT ?person ?type WHERE { ?person a ?type . }
Projection
PREFIX foaf: <http://xmlns.com/foaf/0.1/> # Project specific variables SELECT ?name ?age WHERE { ?person foaf:name ?name ; foaf:age ?age ; foaf:mbox ?email . # Not projected } # Project all variables SELECT * WHERE { ?person foaf:name ?name ; foaf:age ?age . } # Project with expressions SELECT ?person (?age + 1 AS ?nextAge) WHERE { ?person foaf:age ?age . } # Conditional projection SELECT ?person (IF(?age >= 18, "Adult", "Minor") AS ?ageGroup) WHERE { ?person foaf:age ?age . }
Aggregations and Grouping
COUNT Aggregation
PREFIX foaf: <http://xmlns.com/foaf/0.1/> # Count all results SELECT (COUNT(*) AS ?total) WHERE { ?s a foaf:Person . } # Count specific variable SELECT (COUNT(?friend) AS ?friendCount) WHERE { ex:Alice foaf:knows ?friend . } # Count distinct values SELECT (COUNT(DISTINCT ?type) AS ?typeCount) WHERE { ?s a ?type . } # Count with GROUP BY SELECT ?person (COUNT(?friend) AS ?friendCount) WHERE { ?person foaf:knows ?friend . } GROUP BY ?person # Count with HAVING SELECT ?person (COUNT(?friend) AS ?friendCount) WHERE { ?person foaf:knows ?friend . } GROUP BY ?person HAVING (COUNT(?friend) > 5)
Other Aggregations
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX ex: <http://example.org/> # SUM SELECT ?department (SUM(?salary) AS ?totalSalary) WHERE { ?person ex:department ?department ; ex:salary ?salary . } GROUP BY ?department # AVG SELECT ?department (AVG(?salary) AS ?avgSalary) WHERE { ?person ex:department ?department ; ex:salary ?salary . } GROUP BY ?department # MIN and MAX SELECT ?department (MIN(?salary) AS ?minSalary) (MAX(?salary) AS ?maxSalary) WHERE { ?person ex:department ?department ; ex:salary ?salary . } GROUP BY ?department # Multiple aggregations SELECT ?person (COUNT(?friend) AS ?friendCount) (AVG(?friendAge) AS ?avgFriendAge) (MIN(?friendAge) AS ?youngestFriend) (MAX(?friendAge) AS ?oldestFriend) WHERE { ?person foaf:knows ?friend . ?friend foaf:age ?friendAge . } GROUP BY ?person # SAMPLE - arbitrary value from group SELECT ?type (SAMPLE(?s) AS ?example) WHERE { ?s a ?type . } GROUP BY ?type # GROUP_CONCAT - concatenate values SELECT ?person (GROUP_CONCAT(?friendName; separator=", ") AS ?friends) WHERE { ?person foaf:knows ?friend . ?friend foaf:name ?friendName . } GROUP BY ?person
GROUP BY Clause
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX ex: <http://example.org/> # Basic GROUP BY SELECT ?type (COUNT(?s) AS ?count) WHERE { ?s a ?type . } GROUP BY ?type # Multiple grouping variables SELECT ?department ?location (COUNT(?person) AS ?count) WHERE { ?person ex:department ?department ; ex:location ?location . } GROUP BY ?department ?location # GROUP BY with expressions SELECT (FLOOR(?age/10) AS ?ageDecade) (COUNT(?person) AS ?count) WHERE { ?person foaf:age ?age . } GROUP BY (FLOOR(?age/10)) # Nested aggregations require subqueries SELECT ?person ?name ?friendCount WHERE { ?person foaf:name ?name . { SELECT ?person (COUNT(?friend) AS ?friendCount) WHERE { ?person foaf:knows ?friend . } GROUP BY ?person } } ORDER BY DESC(?friendCount)
HAVING Clause
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX ex: <http://example.org/> # Filter groups by aggregate value SELECT ?person (COUNT(?friend) AS ?friendCount) WHERE { ?person foaf:knows ?friend . } GROUP BY ?person HAVING (COUNT(?friend) > 5) # Multiple HAVING conditions SELECT ?department (COUNT(?person) AS ?count) (AVG(?salary) AS ?avgSalary) WHERE { ?person ex:department ?department ; ex:salary ?salary . } GROUP BY ?department HAVING (COUNT(?person) > 10 && AVG(?salary) > 50000) # HAVING with bound variables SELECT ?person (COUNT(?friend) AS ?friendCount) WHERE { ?person foaf:knows ?friend ; foaf:age ?age . } GROUP BY ?person HAVING (COUNT(?friend) > 3 && ?age < 30)
Property Paths
Basic Property Paths
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX ex: <http://example.org/> # Zero or more (*) SELECT ?person ?ancestor WHERE { ?person ex:hasParent* ?ancestor . } # One or more (+) SELECT ?person ?descendant WHERE { ?person ex:hasChild+ ?descendant . } # Zero or one (?) SELECT ?person ?contact WHERE { ?person ex:primaryContact? ?contact . } # Exact number {n} SELECT ?person ?relative WHERE { ?person ex:hasParent{2} ?relative . # Grandparents } # Range {n,m} SELECT ?person ?ancestor WHERE { ?person ex:hasParent{1,3} ?ancestor . # Parents, grandparents, great-grandparents } # At least n {n,} SELECT ?person ?ancestor WHERE { ?person ex:hasParent{2,} ?ancestor . # Grandparents and beyond }
Path Alternatives
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX vcard: <http://www.w3.org/2006/vcard/ns#> # Alternative paths (|) SELECT ?person ?name WHERE { ?person foaf:name|vcard:fn ?name . } # Complex alternatives SELECT ?person ?contact WHERE { ?person foaf:mbox|foaf:phone|vcard:email ?contact . } # Alternatives with paths SELECT ?person ?relative WHERE { ?person (ex:hasParent|ex:hasChild)+ ?relative . }
Path Sequences
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX ex: <http://example.org/> # Sequence (/) SELECT ?person ?friendOfFriend WHERE { ?person foaf:knows/foaf:knows ?friendOfFriend . FILTER (?person != ?friendOfFriend) } # Longer sequences SELECT ?person ?greatGrandparent WHERE { ?person ex:hasParent/ex:hasParent/ex:hasParent ?greatGrandparent . } # Mixed sequences and alternatives SELECT ?person ?contact WHERE { ?person foaf:knows/foaf:mbox|foaf:phone ?contact . } # Sequences with repetition SELECT ?person ?colleague WHERE { ?person (ex:worksFor/ex:employs)+ ?colleague . }
Inverse Paths
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX ex: <http://example.org/> # Inverse path (^) SELECT ?child ?parent WHERE { ?child ^ex:hasChild ?parent . # Equivalent to: ?parent ex:hasChild ?child . } # Inverse with repetition SELECT ?person ?descendant WHERE { ?person ^ex:hasParent+ ?descendant . } # Complex inverse paths SELECT ?person ?manager WHERE { ?person ^ex:manages/ex:worksFor ?manager . }
Negated Property Paths
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX ex: <http://example.org/> # Negated property set (!) SELECT ?s ?o WHERE { ?s !rdf:type ?o . # Any property except rdf:type } # Negated alternative SELECT ?person ?value WHERE { ?person !(foaf:name|foaf:mbox) ?value . } # Negated in path SELECT ?person ?other WHERE { ?person !foaf:knows/foaf:name ?other . }
Complex Property Path Examples
PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX ex: <http://example.org/> # Social network exploration SELECT ?person ?distance ?connection WHERE { ex:Alice (foaf:knows+) ?connection . BIND (strlen(?path) AS ?distance) } # Organizational hierarchy SELECT ?employee ?boss WHERE { ?employee ex:reportsTo+ ?boss . ?boss ex:title "CEO" . } # Family tree SELECT ?person ?bloodRelative WHERE { ?person (ex:hasParent|^ex:hasParent|ex:hasSibling)+ ?bloodRelative . FILTER (?person != ?bloodRelative) } # Transitive closure with cycle detection SELECT DISTINCT ?start ?end WHERE { VALUES ?start { ex:NodeA } ?start ex:linksTo+ ?end . } # Path with intermediate nodes SELECT ?person ?friend ?friendOfFriend ?skill WHERE { ?person foaf:knows ?friend . ?friend foaf:knows ?friendOfFriend . ?friendOfFriend ex:hasSkill ?skill . FILTER (?person != ?friendOfFriend) }
Federated Queries
SERVICE Keyword
PREFIX foaf: <http://xmlns.com/foaf/0.1/> # Basic federated query SELECT ?person ?name WHERE { # Local query ?person a foaf:Person . # Remote query to DBpedia SERVICE <http://dbpedia.org/sparql> { ?person foaf:name ?name . } } # SERVICE with OPTIONAL SELECT ?person ?dbpediaInfo WHERE { ?person a foaf:Person . OPTIONAL { SERVICE <http://dbpedia.org/sparql> { ?person rdfs:label ?dbpediaInfo . FILTER (lang(?dbpediaInfo) = "en") } } } # Multiple SERVICE endpoints SELECT ?person ?name ?bio WHERE { ?person a foaf:Person . SERVICE <http://dbpedia.org/sparql> { ?person foaf:name ?name . } SERVICE <http://example.org/sparql> { ?person ex:biography ?bio . } }
SERVICE SILENT
PREFIX foaf: <http://xmlns.com/foaf/0.1/> # Silently fail if remote endpoint unavailable SELECT ?person ?name WHERE { ?person a foaf:Person . SERVICE SILENT <http://dbpedia.org/sparql> { ?person foaf:name ?name . } } # Fallback pattern with multiple services SELECT ?person ?info WHERE { ?person a foaf:Person . { SERVICE SILENT <http://primary.example.org/sparql> { ?person ex:info ?info . } } UNION { SERVICE SILENT <http://backup.example.org/sparql> { ?person ex:info ?info . } } }
Wikidata Examples
PREFIX wd: <http://www.wikidata.org/entity/> PREFIX wdt: <http://www.wikidata.org/prop/direct/> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> # Query Wikidata for cities SELECT ?city ?cityLabel ?population WHERE { SERVICE <https://query.wikidata.org/sparql> { ?city wdt:P31 wd:Q515 ; # Instance of city wdt:P1082 ?population ; # Population rdfs:label ?cityLabel . FILTER (lang(?cityLabel) = "en") FILTER (?population > 1000000) } } ORDER BY DESC(?population) LIMIT 10 # Query for programming languages SELECT ?lang ?langLabel ?influenced WHERE { SERVICE <https://query.wikidata.org/sparql> { ?lang wdt:P31 wd:Q9143 ; # Instance of programming language wdt:P737 ?influenced ; # Influenced by rdfs:label ?langLabel . FILTER (lang(?langLabel) = "en") } }
DBpedia Examples
PREFIX dbo: <http://dbpedia.org/ontology/> PREFIX dbr: <http://dbpedia.org/resource/> # Query DBpedia for movies SELECT ?movie ?title ?director WHERE { SERVICE <http://dbpedia.org/sparql> { ?movie a dbo:Film ; dbo:director ?director ; rdfs:label ?title . FILTER (lang(?title) = "en") FILTER (regex(?title, "Star Wars")) } } # Query for geographical data SELECT ?country ?capital ?population WHERE { SERVICE <http://dbpedia.org/sparql> { ?country a dbo:Country ; dbo:capital ?capital ; dbo:populationTotal ?population . FILTER (?population > 50000000) } } ORDER BY DESC(?population)
Common Ontologies
RDF Schema (RDFS)
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> # Class hierarchy SELECT ?class ?superClass WHERE { ?class rdfs:subClassOf ?superClass . } # Property hierarchy SELECT ?property ?superProperty WHERE { ?property rdfs:subPropertyOf ?superProperty . } # Labels and comments SELECT ?resource ?label ?comment WHERE { ?resource rdfs:label ?label ; rdfs:comment ?comment . FILTER (lang(?label) = "en") } # Domain and range SELECT ?property ?domain ?range WHERE { ?property rdfs:domain ?domain ; rdfs:range ?range . } # Type inference SELECT ?resource ?type WHERE { ?resource a ?directType . ?directType rdfs:subClassOf* ?type . }
FOAF (Friend of a Friend)
PREFIX foaf: <http://xmlns.com/foaf/0.1/> # Person information SELECT ?person ?name ?email ?homepage WHERE { ?person a foaf:Person ; foaf:name ?name . OPTIONAL { ?person foaf:mbox ?email } OPTIONAL { ?person foaf:homepage ?homepage } } # Social network SELECT ?person ?friend ?friendName WHERE { ?person foaf:name "Alice" ; foaf:knows ?friend . ?friend foaf:name ?friendName . } # Organizations SELECT ?org ?name ?member WHERE { ?org a foaf:Organization ; foaf:name ?name ; foaf:member ?member . } # Accounts SELECT ?person ?account ?accountName WHERE { ?person foaf:account ?account . ?account foaf:accountName ?accountName . }
Dublin Core
PREFIX dc: <http://purl.org/dc/elements/1.1/> PREFIX dcterms: <http://purl.org/dc/terms/> # Metadata queries SELECT ?resource ?title ?creator ?date WHERE { ?resource dc:title ?title ; dc:creator ?creator ; dc:date ?date . } # Subject classification SELECT ?resource ?subject WHERE { ?resource dc:subject ?subject . } # Rights and license SELECT ?resource ?rights ?license WHERE { ?resource dcterms:rights ?rights ; dcterms:license ?license . }
SKOS (Simple Knowledge Organization System)
PREFIX skos: <http://www.w3.org/2004/02/skos/core#> # Concept schemes SELECT ?concept ?prefLabel ?scheme WHERE { ?concept a skos:Concept ; skos:prefLabel ?prefLabel ; skos:inScheme ?scheme . FILTER (lang(?prefLabel) = "en") } # Hierarchical relations SELECT ?broader ?concept ?narrower WHERE { ?concept skos:broader ?broader ; skos:narrower ?narrower . } # Related concepts SELECT ?concept ?related WHERE { ?concept skos:related ?related . } # Alternative labels SELECT ?concept ?prefLabel ?altLabel WHERE { ?concept skos:prefLabel ?prefLabel ; skos:altLabel ?altLabel . FILTER (lang(?prefLabel) = "en") }
OWL (Web Ontology Language)
PREFIX owl: <http://www.w3.org/2002/07/owl#> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> # OWL classes SELECT ?class WHERE { ?class a owl:Class . } # Equivalent classes SELECT ?class1 ?class2 WHERE { ?class1 owl:equivalentClass ?class2 . } # Disjoint classes SELECT ?class1 ?class2 WHERE { ?class1 owl:disjointWith ?class2 . } # Object properties SELECT ?property ?domain ?range WHERE { ?property a owl:ObjectProperty ; rdfs:domain ?domain ; rdfs:range ?range . } # Datatype properties SELECT ?property ?domain ?range WHERE { ?property a owl:DatatypeProperty ; rdfs:domain ?domain ; rdfs:range ?range . } # Property characteristics SELECT ?property ?characteristic WHERE { ?property a owl:ObjectProperty . { ?property a owl:SymmetricProperty . BIND ("Symmetric" AS ?characteristic) } UNION { ?property a owl:TransitiveProperty . BIND ("Transitive" AS ?characteristic) } UNION { ?property a owl:FunctionalProperty . BIND ("Functional" AS ?characteristic) } } # Restrictions SELECT ?class ?property ?restriction WHERE { ?class rdfs:subClassOf ?restriction . ?restriction a owl:Restriction ; owl:onProperty ?property . }
Schema.org
PREFIX schema: <http://schema.org/> # Organizations SELECT ?org ?name ?url WHERE { ?org a schema:Organization ; schema:name ?name ; schema:url ?url . } # People SELECT ?person ?name ?email ?jobTitle WHERE { ?person a schema:Person ; schema:name ?name ; schema:email ?email ; schema:jobTitle ?jobTitle . } # Events SELECT ?event ?name ?startDate ?location WHERE { ?event a schema:Event ; schema:name ?name ; schema:startDate ?startDate ; schema:location ?location . } # Products SELECT ?product ?name ?price ?brand WHERE { ?product a schema:Product ; schema:name ?name ; schema:offers/schema:price ?price ; schema:brand ?brand . }
Best Practices
Query Optimization
# ✓ Good: Specific patterns first SELECT ?person ?name WHERE { ?person foaf:name "Alice" . # Specific ?person foaf:knows ?friend . # More general ?friend foaf:name ?name . } # ✗ Bad: General patterns first SELECT ?person ?name WHERE { ?person foaf:knows ?friend . # Too general first ?friend foaf:name ?name . ?person foaf:name "Alice" . # Specific last } # ✓ Good: Use FILTER efficiently SELECT ?person ?age WHERE { ?person foaf:age ?age . FILTER (?age >= 18 && ?age < 65) } # ✗ Bad: Multiple separate FILTERs SELECT ?person ?age WHERE { ?person foaf:age ?age . FILTER (?age >= 18) FILTER (?age < 65) } # ✓ Good: Use property paths when appropriate SELECT ?person ?ancestor WHERE { ?person ex:hasParent+ ?ancestor . } # ✗ Bad: Manual recursion (verbose and limited) SELECT ?person ?ancestor WHERE { { ?person ex:hasParent ?ancestor . } UNION { ?person ex:hasParent/ex:hasParent ?ancestor . } UNION { ?person ex:hasParent/ex:hasParent/ex:hasParent ?ancestor . } }
Using Prefixes Effectively
# ✓ Good: Define all prefixes at the start PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> PREFIX foaf: <http://xmlns.com/foaf/0.1/> PREFIX ex: <http://example.org/> SELECT ?person ?name WHERE { ?person a foaf:Person ; foaf:name ?name . } # ✗ Bad: Full URIs in query SELECT ?person ?name WHERE { ?person a <http://xmlns.com/foaf/0.1/Person> ; <http://xmlns.com/foaf/0.1/name> ?name . }
Handling Optional Data
# ✓ Good: Use OPTIONAL for truly optional data SELECT ?person ?name ?email WHERE { ?person foaf:name ?name . OPTIONAL { ?person foaf:mbox ?email . } } # ✓ Good: Provide defaults with COALESCE SELECT ?person ?contact WHERE { ?person foaf:name ?name . OPTIONAL { ?person foaf:mbox ?email } OPTIONAL { ?person foaf:phone ?phone } BIND (COALESCE(?email, ?phone, "No contact") AS ?contact) } # ✓ Good: Check for bound variables SELECT ?person ?name WHERE { ?person foaf:name ?name . OPTIONAL { ?person foaf:mbox ?email } FILTER (bound(?email)) }
Type Safety and Validation
# ✓ Good: Validate data types SELECT ?person ?age WHERE { ?person foaf:age ?age . FILTER (datatype(?age) = xsd:integer) FILTER (?age >= 0 && ?age < 150) } # ✓ Good: Handle language tags SELECT ?resource ?label WHERE { ?resource rdfs:label ?label . FILTER (lang(?label) = "en" || lang(?label) = "") } # ✓ Good: Validate URIs SELECT ?person ?homepage WHERE { ?person foaf:homepage ?homepage . FILTER (isURI(?homepage)) FILTER (strstarts(str(?homepage), "https://")) }
Reusable Query Patterns
# Pattern: Pagination SELECT ?person ?name WHERE { ?person foaf:name ?name . } ORDER BY ?name LIMIT 20 OFFSET 0 # Increment by 20 for each page # Pattern: Search with ranking SELECT ?resource ?label (SUM(?score) AS ?totalScore) WHERE { { ?resource rdfs:label ?label . FILTER (contains(lcase(?label), "search term")) BIND (10 AS ?score) } UNION { ?resource rdfs:comment ?comment . FILTER (contains(lcase(?comment), "search term")) BIND (5 AS ?score) } } GROUP BY ?resource ?label ORDER BY DESC(?totalScore) # Pattern: Existence check SELECT ?resource WHERE { ?resource a ex:RequiredType . FILTER EXISTS { ?resource ex:requiredProperty ?value } FILTER NOT EXISTS { ?resource ex:forbiddenProperty ?any } } # Pattern: Hierarchical query with depth limit SELECT ?parent ?child ?depth WHERE { VALUES ?root { ex:StartNode } ?root ex:hasChild{1,3} ?child . ?child ^ex:hasChild{1,3} ?parent . BIND (/* calculate depth */ AS ?depth) }
Error Prevention
# ✓ Good: Avoid division by zero SELECT ?person ((?total / ?count) AS ?average) WHERE { ?person ex:total ?total ; ex:count ?count . FILTER (?count != 0) } # ✓ Good: Handle missing language tags SELECT ?resource ?label WHERE { ?resource rdfs:label ?label . FILTER ( !bound(lang(?label)) || lang(?label) = "" || lang(?label) = "en" ) } # ✓ Good: Safe string operations SELECT ?person ?name ?initial WHERE { ?person foaf:name ?name . FILTER (strlen(?name) > 0) BIND (substr(?name, 1, 1) AS ?initial) }
Performance Considerations
# ✓ Good: Limit early when exploring SELECT ?s ?p ?o WHERE { ?s ?p ?o . } LIMIT 100 # ✓ Good: Use COUNT efficiently SELECT (COUNT(*) AS ?count) WHERE { ?s a foaf:Person . } # ✓ Good: Avoid expensive operations in FILTER SELECT ?person ?name WHERE { ?person foaf:name ?name . ?person foaf:age ?age . } HAVING (?age > 18) # Better in HAVING for grouped results # ✗ Bad: Expensive regex in FILTER SELECT ?person ?name WHERE { ?person foaf:name ?name . FILTER (regex(?name, "^[A-Z][a-z]+\\s[A-Z][a-z]+$")) } # Better: Check format on application side if possible
This skill provides foundational SPARQL patterns for querying RDF data and working with knowledge graphs. These patterns cover standard query operations, graph patterns, aggregations, property paths, federated queries, and common semantic web ontologies. Use this as a reference for SPARQL development and semantic web applications.