# SPARQL Query Reference for Graph Studio

This document provides SPARQL patterns and best practices for querying Siemens Graph Studio GraphMarts.

## Key Principle: Always Use Discovered URIs

Ontologies define their own URI patterns — never assume or guess. Always use the exact URIs returned by `discover_knowledge_overview` or `discover_class_data_properties`.

---

## Essential Query Patterns

### 1. Discover Available Classes
```sparql
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT DISTINCT ?type (COUNT(?s) as ?count)
WHERE {
    ?s rdf:type ?type .
}
GROUP BY ?type
ORDER BY DESC(?count)
LIMIT 20
```

### 2. Inspect Properties of a Class
```sparql
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT DISTINCT ?property (SAMPLE(?value) as ?exampleValue) (COUNT(?instance) as ?usageCount)
WHERE {
    ?instance rdf:type <YOUR_CLASS_URI> .
    ?instance ?property ?value .
}
GROUP BY ?property
ORDER BY DESC(?usageCount)
LIMIT 50
```

### 3. Sample Complete Entities
```sparql
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT ?instance ?property ?value
WHERE {
    ?instance rdf:type <YOUR_CLASS_URI> .
    ?instance ?property ?value .
}
LIMIT 100
```

### 4. Count Instances (Verify Data Exists)
```sparql
SELECT (COUNT(?instance) as ?count)
WHERE {
    ?instance rdf:type <YOUR_CLASS_URI> .
}
```

### 5. Find Related Classes
```sparql
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT DISTINCT ?relatedClass (COUNT(?related) as ?count)
WHERE {
    ?instance rdf:type <YOUR_CLASS_URI> .
    ?instance ?property ?related .
    ?related rdf:type ?relatedClass .
}
GROUP BY ?relatedClass
ORDER BY DESC(?count)
```

---

## Query Best Practices

### Always Use LIMIT
Prevent timeouts and overwhelming responses:
```sparql
SELECT ?s ?p ?o
WHERE { ?s ?p ?o }
LIMIT 50
```

### Use OPTIONAL for Non-Required Properties
Some instances may not have all properties:
```sparql
SELECT ?item ?name ?description
WHERE {
    ?item rdf:type <CLASS_URI> .
    ?item <NAME_PROPERTY_URI> ?name .
    OPTIONAL { ?item <DESCRIPTION_PROPERTY_URI> ?description }
}
LIMIT 50
```

### Text Search with FILTER
Case-insensitive substring matching:
```sparql
SELECT ?item ?name
WHERE {
    ?item rdf:type <CLASS_URI> .
    ?item <NAME_PROPERTY_URI> ?name .
    FILTER(CONTAINS(LCASE(STR(?name)), "search term"))
}
LIMIT 50
```

### Use DISTINCT to Remove Duplicates
```sparql
SELECT DISTINCT ?category
WHERE {
    ?item rdf:type <CLASS_URI> .
    ?item <CATEGORY_PROPERTY_URI> ?category .
}
```

### Aggregations
```sparql
SELECT ?category (COUNT(?item) as ?count) (AVG(?price) as ?avgPrice)
WHERE {
    ?item rdf:type <CLASS_URI> .
    ?item <CATEGORY_PROPERTY_URI> ?category .
    ?item <PRICE_PROPERTY_URI> ?price .
}
GROUP BY ?category
ORDER BY DESC(?count)
```

---

## Common Pitfalls

### ❌ Wrong: Guessing Property Names
```sparql
SELECT ?shift ?name ?start
WHERE {
    ?shift a :Shift ;
           :shiftName ?name ;      # ← Invented names
           :startTime ?start .
}
```

### ✅ Correct: Use Discovered URIs
```sparql
# Use exact URIs from discover_knowledge_overview
SELECT ?shift ?startTime
WHERE {
    ?shift rdf:type <CLASS_URI_FROM_OVERVIEW> .
    ?shift <PROPERTY_URI_FROM_OVERVIEW> ?startTime .
}
```

### ❌ Wrong: No LIMIT Clause
```sparql
SELECT * WHERE { ?s ?p ?o }  # May return millions of rows
```

### ✅ Correct: Always Include LIMIT
```sparql
SELECT * WHERE { ?s ?p ?o } LIMIT 100
```

### ❌ Wrong: Assuming rdfs:label Exists
```sparql
?item rdfs:label ?name .  # May not exist in custom ontologies
```

### ✅ Correct: Check Actual Properties
```sparql
# First discover what properties exist using discovery tools, then use those URIs
?item <DISCOVERED_PROPERTY_URI> ?name .
```

---

## Retry Strategy

When a query returns empty results or errors:

### Step 1: Verify Class Has Instances
```sparql
SELECT (COUNT(?i) as ?count) WHERE { ?i rdf:type <YOUR_CLASS_URI> }
```

### Step 2: Make Properties OPTIONAL
```sparql
SELECT ?item ?name ?description
WHERE {
    ?item rdf:type <CLASS_URI> .
    OPTIONAL { ?item <NAME_PROPERTY_URI> ?name }
    OPTIONAL { ?item <DESCRIPTION_PROPERTY_URI> ?description }
}
LIMIT 50
```

### Step 3: Inspect Actual Data Structure
```sparql
SELECT DISTINCT ?property
WHERE {
    ?instance rdf:type <YOUR_CLASS_URI> .
    ?instance ?property ?value .
}
```

### Step 4: If Still No Results
Stop and ask the user for clarification. Share what you discovered:
- What classes exist
- What properties you found
- What you searched for

---

## Performance Tips

1. **Filter Early**: Apply WHERE conditions before aggregations
2. **Use DISTINCT Only When Needed**: It adds processing overhead
3. **Order Intentionally**: Only use ORDER BY when the order matters
4. **Prefer Specific Patterns**: `?s a ont:Class` is faster than `?s ?p ?o`
5. **Avoid Cartesian Products**: Be careful with multiple unconnected patterns

---

## Namespace Quick Reference

Common namespaces in Graph Studio:

```sparql
PREFIX rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl:  <http://www.w3.org/2002/07/owl#>
PREFIX xsd:  <http://www.w3.org/2001/XMLSchema#>

# GraphMart system namespace
PREFIX gm: <http://cambridgesemantics.com/ontologies/Graphmarts#>
```

Custom ontology namespaces will be provided by the `discover_knowledge_overview` tool.
