Each card below represents an example query from /Users/kidehen/Documents/Database Scripts /Queries/SPARQL/Sales Reports/customer-analysis.rq. Click the button to run it against http://oplussol10.intranet.openlinksw.com:8893/sparql and see the live results rendered by the SPARQL service.
QUERY 1: Most Recent Order Date (Basic) ============================================================================== Finds companies whose most recent order was 2+ years ago Use Case: Identify inactive customers for re-engagement
PREFIX ecrm-ontology: <http://www.openlinksw.com/ontology/ecrm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT DISTINCT ?company ?mostRecentOrderDate
WHERE {
{
SELECT ?company (MAX(?orderDate) AS ?mostRecentOrderDate)
WHERE {
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
GROUP BY ?company
}
FILTER (?mostRecentOrderDate <= (NOW() - "P2Y"^^xsd:duration))
}
ORDER BY ?mostRecentOrderDate
LIMIT 10 ;
Tweak that adds company name, and for most recent 5 years
PREFIX ecrm-ontology: <http://www.openlinksw.com/ontology/ecrm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX schema: <http://schema.org/>
SELECT DISTINCT ?company ?companyName ?mostRecentOrderDate round(?daysSinceLastOrder) as ?daysSinceLastOrder
WHERE {
{
SELECT ?company (MAX(?orderDate) AS ?mostRecentOrderDate)
WHERE {
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
GROUP BY ?company
}
FILTER (?mostRecentOrderDate <= (NOW() - "P5Y"^^xsd:duration))
OPTIONAL { ?company schema:name|rdfs:label ?companyName }
BIND((NOW() - ?mostRecentOrderDate) AS ?daysSinceLastOrder)
}
ORDER BY DESC(?mostRecentOrderDate)
LIMIT 20 ;
## ==============================================================================
QUERY 2: Most Recent Order Date with Order Count ============================================================================== Adds total order count to identify high-value dormant customers Use Case: Prioritize re-engagement by customer lifetime value
PREFIX ecrm-ontology: <http://www.openlinksw.com/ontology/ecrm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?company ?mostRecentOrderDate ?totalOrders
WHERE {
{
SELECT ?company (MAX(?orderDate) AS ?mostRecentOrderDate) (COUNT(DISTINCT ?order) AS ?totalOrders)
WHERE {
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
GROUP BY ?company
}
FILTER (?mostRecentOrderDate <= (NOW() - "P2Y"^^xsd:duration))
}
ORDER BY DESC(?totalOrders) ?mostRecentOrderDate
LIMIT 10 ;
## ==============================================================================
QUERY 2A: With Oldest Order Date - Customer Lifetime Analysis ============================================================================== Includes both oldest and most recent order dates to show customer lifetime Use Case: Understand customer tenure and engagement span
PREFIX ecrm-ontology: <http://www.openlinksw.com/ontology/ecrm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?company ?oldestOrderDate ?mostRecentOrderDate ?totalOrders ?customerLifetimeYears
WHERE {
{
SELECT ?company
(MIN(?orderDate) AS ?oldestOrderDate)
(MAX(?orderDate) AS ?mostRecentOrderDate)
(COUNT(DISTINCT ?order) AS ?totalOrders)
WHERE {
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
GROUP BY ?company
}
FILTER (?mostRecentOrderDate <= (NOW() - "P2Y"^^xsd:duration))
# Calculate customer lifetime in years
BIND((?mostRecentOrderDate - ?oldestOrderDate) / 365.25 AS ?customerLifetimeYears)
}
ORDER BY DESC(?totalOrders) ?mostRecentOrderDate
LIMIT 50 ;
## ==============================================================================
QUERY 2B: Comprehensive Customer Lifetime with Details ============================================================================== Full customer analysis with first/last order, tenure, and company details Use Case: Executive dashboard showing complete customer lifecycle metrics
PREFIX ecrm-ontology: <http://www.openlinksw.com/ontology/ecrm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX schema: <http://schema.org/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?company ?companyName
?oldestOrderDate ?mostRecentOrderDate
?totalOrders
(ROUND(?customerLifetimeYears * 10) / 10 AS ?lifetimeYears)
(ROUND(?daysSinceLastOrder) AS ?daysSinceLastOrder)
(ROUND(?avgOrdersPerYear * 10) / 10 AS ?avgOrdersPerYear)
WHERE {
{
SELECT ?company
(MIN(?orderDate) AS ?oldestOrderDate)
(MAX(?orderDate) AS ?mostRecentOrderDate)
(COUNT(DISTINCT ?order) AS ?totalOrders)
WHERE {
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
GROUP BY ?company
}
FILTER (?mostRecentOrderDate <= (NOW() - "P2Y"^^xsd:duration))
# Get company name
OPTIONAL { ?company schema:name|rdfs:label ?companyName }
# Calculate metrics
BIND((?mostRecentOrderDate - ?oldestOrderDate) / 365.25 AS ?customerLifetimeYears)
BIND((NOW() - ?mostRecentOrderDate) AS ?daysSinceLastOrder)
BIND(
IF(?customerLifetimeYears > 0,
?totalOrders / ?customerLifetimeYears,
0)
AS ?avgOrdersPerYear
)
}
ORDER BY DESC(?totalOrders) ?mostRecentOrderDate
LIMIT 50 ;
## ==============================================================================
QUERY 2C: Aggregated with Sample Order URI (Best of Both) ============================================================================== Aggregated view with a sample order URI for drill-down capability Use Case: Summary metrics with ability to click through to an example order
PREFIX ecrm-ontology: <http://www.openlinksw.com/ontology/ecrm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX schema: <http://schema.org/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?company ?companyName
?oldestOrderDate ?mostRecentOrderDate
?totalOrders
?sampleOrder
WHERE {
{
SELECT ?company
(MIN(?orderDate) AS ?oldestOrderDate)
(MAX(?orderDate) AS ?mostRecentOrderDate)
(COUNT(DISTINCT ?order) AS ?totalOrders)
(SAMPLE(?order) AS ?sampleOrder)
WHERE {
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
GROUP BY ?company
}
FILTER (?mostRecentOrderDate <= (NOW() - "P2Y"^^xsd:duration))
# Get company name
OPTIONAL { ?company schema:name|rdfs:label ?companyName }
}
ORDER BY DESC(?totalOrders) ?mostRecentOrderDate
LIMIT 50 ;
## ==============================================================================
QUERY 2D: Individual Orders for Inactive Customers (Full Drill-Down) ============================================================================== Shows all individual orders for companies with no orders in the last 2 years Use Case: Click on ?order URIs to drill down into order details
PREFIX ecrm-ontology: <http://www.openlinksw.com/ontology/ecrm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX schema: <http://schema.org/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?company ?companyName ?order ?orderDate ?orderNumber
WHERE {
# Subquery to find inactive companies
{
SELECT ?company (MAX(?orderDate) AS ?mostRecentOrderDate)
WHERE {
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
GROUP BY ?company
HAVING (MAX(?orderDate) <= (NOW() - "P2Y"^^xsd:duration))
}
# Get all orders for these inactive companies
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
# Get company name
OPTIONAL { ?company schema:name|rdfs:label ?companyName }
# Get order number if available
OPTIONAL { ?order ecrm-ontology:hasOrderNumber ?orderNumber }
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
ORDER BY ?company DESC(?orderDate)
LIMIT 200 ;
## ==============================================================================
QUERY 2E: Orders with Items - Product Trend Analysis ============================================================================== Shows orders with item details for inactive customers Use Case: Analyze what products inactive customers were buying
PREFIX ecrm-ontology: <http://www.openlinksw.com/ontology/ecrm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX schema: <http://schema.org/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT DISTINCT ?company ?companyName ?order ?orderDate
?orderItem ?itemLabel
(YEAR(?orderDate) AS ?orderYear)
WHERE {
# Subquery to find inactive companies
{
SELECT ?company (MAX(?orderDate) AS ?mostRecentOrderDate)
WHERE {
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
GROUP BY ?company
HAVING (MAX(?orderDate) <= (NOW() - "P2Y"^^xsd:duration))
}
# Get all orders for these inactive companies
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:hasOrderItem ?orderItem ;
ecrm-ontology:orderDate ?orderDate .
# Get order item label
OPTIONAL { ?orderItem schema:name|rdfs:label ?itemLabel }
# Get company name
OPTIONAL { ?company schema:name|rdfs:label ?companyName }
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
ORDER BY ?company DESC(?orderDate)
LIMIT 300 ;
## ==============================================================================
QUERY 2F: Product Trends by Year for Inactive Customers ============================================================================== Aggregates items by year to show purchasing trends over time Use Case: Identify which products inactive customers bought most in each year
PREFIX ecrm-ontology: <http://www.openlinksw.com/ontology/ecrm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX schema: <http://schema.org/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?orderYear ?itemLabel
(COUNT(DISTINCT ?orderItem) AS ?itemCount)
(COUNT(DISTINCT ?company) AS ?customerCount)
WHERE {
# Subquery to find inactive companies
{
SELECT ?company (MAX(?orderDate) AS ?mostRecentOrderDate)
WHERE {
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
GROUP BY ?company
HAVING (MAX(?orderDate) <= (NOW() - "P2Y"^^xsd:duration))
}
# Get all orders for these inactive companies
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:hasOrderItem ?orderItem ;
ecrm-ontology:orderDate ?orderDate .
# Get order item label
?orderItem schema:name|rdfs:label ?itemLabel .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
BIND(YEAR(?orderDate) AS ?orderYear)
}
GROUP BY ?orderYear ?itemLabel
ORDER BY DESC(?orderYear) DESC(?itemCount)
LIMIT 200 ;
## ==============================================================================
QUERY 2G: Customer Purchase History with Items (Timeline View) ============================================================================== Shows complete purchase timeline for each inactive customer with items Use Case: See what each customer bought over their lifetime, chronologically
PREFIX ecrm-ontology: <http://www.openlinksw.com/ontology/ecrm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX schema: <http://schema.org/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT DISTINCT ?company ?companyName
?orderDate (YEAR(?orderDate) AS ?year)
?order ?orderItem ?itemLabel
?quantity ?price
WHERE {
# Subquery to find inactive companies
{
SELECT ?company (MAX(?orderDate) AS ?mostRecentOrderDate)
WHERE {
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
GROUP BY ?company
HAVING (MAX(?orderDate) <= (NOW() - "P2Y"^^xsd:duration))
}
# Get all orders for these inactive companies
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:hasOrderItem ?orderItem ;
ecrm-ontology:orderDate ?orderDate .
# Get company name
OPTIONAL { ?company schema:name|rdfs:label ?companyName }
# Get order item label
OPTIONAL { ?orderItem schema:name|rdfs:label ?itemLabel }
# Get item quantity and price if available
OPTIONAL { ?orderItem ecrm-ontology:hasQuantity ?quantity }
OPTIONAL { ?orderItem ecrm-ontology:hasPrice ?price }
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
ORDER BY ?company DESC(?orderDate)
LIMIT 500 ;
## ==============================================================================
QUERY 2H: Top Products for Inactive Customers (Summary) ============================================================================== Shows which products are most common among inactive customers Use Case: Identify products that may need attention or improved support
PREFIX ecrm-ontology: <http://www.openlinksw.com/ontology/ecrm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX schema: <http://schema.org/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?itemLabel
(COUNT(DISTINCT ?company) AS ?inactiveCustomerCount)
(COUNT(DISTINCT ?orderItem) AS ?totalItemsSold)
(MIN(?orderDate) AS ?firstSold)
(MAX(?orderDate) AS ?lastSold)
WHERE {
# Subquery to find inactive companies
{
SELECT ?company (MAX(?orderDate) AS ?mostRecentOrderDate)
WHERE {
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
GROUP BY ?company
HAVING (MAX(?orderDate) <= (NOW() - "P2Y"^^xsd:duration))
}
# Get all orders for these inactive companies
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:hasOrderItem ?orderItem ;
ecrm-ontology:orderDate ?orderDate .
# Get order item label
?orderItem schema:name|rdfs:label ?itemLabel .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
GROUP BY ?itemLabel
ORDER BY DESC(?inactiveCustomerCount) DESC(?totalItemsSold)
LIMIT 100 ;
## ==============================================================================
QUERY 3: Inactive Customers with Company Details ============================================================================== Includes company name and calculates days since last order Use Case: Generate detailed customer retention reports
PREFIX ecrm-ontology: <http://www.openlinksw.com/ontology/ecrm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX schema: <http://schema.org/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT DISTINCT ?company ?companyName ?mostRecentOrderDate ?daysSinceLastOrder
WHERE {
{
SELECT ?company (MAX(?orderDate) AS ?mostRecentOrderDate)
WHERE {
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
GROUP BY ?company
}
FILTER (?mostRecentOrderDate <= (NOW() - "P2Y"^^xsd:duration))
OPTIONAL { ?company schema:name ?companyName }
OPTIONAL { ?company rdfs:label ?companyName }
BIND((NOW() - ?mostRecentOrderDate) AS ?daysSinceLastOrder)
}
ORDER BY ?mostRecentOrderDate
LIMIT 10 ;
## ==============================================================================
QUERY 4: Configurable Time Period - 1 Year ============================================================================== Same as Query 1 but for 1 year inactivity threshold Use Case: Earlier intervention for at-risk customers
PREFIX ecrm-ontology: <http://www.openlinksw.com/ontology/ecrm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT DISTINCT ?company ?mostRecentOrderDate
WHERE {
{
SELECT ?company (MAX(?orderDate) AS ?mostRecentOrderDate)
WHERE {
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
GROUP BY ?company
}
# Change duration as needed: P1Y (1 year), P6M (6 months), P90D (90 days)
FILTER (?mostRecentOrderDate <= (NOW() - "P1Y"^^xsd:duration))
}
ORDER BY ?mostRecentOrderDate
LIMIT 10 ;
## ==============================================================================
QUERY 5: Configurable Time Period - 6 Months ============================================================================== For more frequent customer health checks
PREFIX ecrm-ontology: <http://www.openlinksw.com/ontology/ecrm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT DISTINCT ?company ?mostRecentOrderDate
WHERE {
{
SELECT ?company (MAX(?orderDate) AS ?mostRecentOrderDate)
WHERE {
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
GROUP BY ?company
}
FILTER (?mostRecentOrderDate <= (NOW() - "P6M"^^xsd:duration))
}
ORDER BY ?mostRecentOrderDate
LIMIT 10 ;
## ==============================================================================
QUERY 6: Comprehensive Customer Activity Analysis ============================================================================== Includes order count, total revenue, account manager, and customer stage Use Case: Executive dashboard for customer retention
PREFIX ecrm-ontology: <http://www.openlinksw.com/ontology/ecrm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX schema: <http://schema.org/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
SELECT ?company ?companyName ?mostRecentOrderDate
?totalOrders ?accountManagerName ?stage
WHERE {
{
SELECT ?company (MAX(?orderDate) AS ?mostRecentOrderDate) (COUNT(DISTINCT ?order) AS ?totalOrders)
WHERE {
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
GROUP BY ?company
}
FILTER (?mostRecentOrderDate <= (NOW() - "P2Y"^^xsd:duration))
# Get company details
OPTIONAL { ?company schema:name ?companyName }
OPTIONAL { ?company rdfs:label ?companyName }
# Get account manager
OPTIONAL {
?company ecrm-ontology:hasAccountManager ?accountManager .
?accountManager foaf:name ?accountManagerName .
}
# Get customer lifecycle stage
OPTIONAL { ?company ecrm-ontology:hasStage ?stage }
}
ORDER BY DESC(?totalOrders) ?mostRecentOrderDate
LIMIT 20 ;
## ==============================================================================
QUERY 7: At-Risk High-Value Customers ============================================================================== Identifies customers who haven't ordered in 1-2 years but have significant order history Use Case: Targeted re-engagement campaigns for valuable customers
PREFIX ecrm-ontology: <http://www.openlinksw.com/ontology/ecrm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX schema: <http://schema.org/>
SELECT ?company ?companyName ?mostRecentOrderDate ?totalOrders
WHERE {
{
SELECT ?company (MAX(?orderDate) AS ?mostRecentOrderDate) (COUNT(DISTINCT ?order) AS ?totalOrders)
WHERE {
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
GROUP BY ?company
}
# Between 1 and 2 years since last order
FILTER (?mostRecentOrderDate <= (NOW() - "P1Y"^^xsd:duration))
FILTER (?mostRecentOrderDate > (NOW() - "P2Y"^^xsd:duration))
# High-value customers (10+ orders)
FILTER (?totalOrders >= 10)
OPTIONAL { ?company schema:name ?companyName }
}
ORDER BY DESC(?totalOrders) ?mostRecentOrderDate
LIMIT 10 ;
## ==============================================================================
QUERY 8: Customer Segmentation by Order Recency ============================================================================== Categorizes all customers by how recently they ordered Use Case: RFM (Recency, Frequency, Monetary) analysis
PREFIX ecrm-ontology: <http://www.openlinksw.com/ontology/ecrm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX schema: <http://schema.org/>
SELECT ?company ?companyName ?mostRecentOrderDate ?totalOrders ?recencySegment
WHERE {
{
SELECT ?company (MAX(?orderDate) AS ?mostRecentOrderDate) (COUNT(DISTINCT ?order) AS ?totalOrders)
WHERE {
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
}
GROUP BY ?company
}
OPTIONAL { ?company schema:name ?companyName }
BIND(
IF(?mostRecentOrderDate > (NOW() - "P6M"^^xsd:duration), "Active",
IF(?mostRecentOrderDate > (NOW() - "P1Y"^^xsd:duration), "At Risk",
IF(?mostRecentOrderDate > (NOW() - "P2Y"^^xsd:duration), "Dormant",
"Inactive")))
AS ?recencySegment
)
}
ORDER BY ?mostRecentOrderDate
LIMIT 100 ;
## ==============================================================================
ORIGINAL QUERY (For Reference) ============================================================================== Returns any order older than 2 years (can return multiple rows per company)
PREFIX ecrm-ontology: <http://www.openlinksw.com/ontology/ecrm#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT DISTINCT ?company ?orderDate
WHERE {
?order a ecrm-ontology:Order ;
ecrm-ontology:hasCompany ?company ;
ecrm-ontology:orderDate ?orderDate .
FILTER (datatype(?orderDate) IN (xsd:date, xsd:dateTime))
FILTER (?orderDate <= (NOW() - "P2Y"^^xsd:duration))
}
LIMIT 10 ;
## ==============================================================================
## NOTES
## ==============================================================================
#
# Key Differences Between Original and Derivative Queries:
#
# 1. AGGREGATION: Derivative queries use MAX(?orderDate) to find most recent order
# 2. GROUP BY: Groups by company to get one row per company
# 3. DISTINCT COUNTING: Uses COUNT(DISTINCT ?order) to ensure accurate order counts
# (prevents duplicate counting if order data has redundant triples)
# 4. BUSINESS LOGIC: Most recent order date better identifies truly inactive customers
# 5. ACTIONABILITY: Results are more useful for customer retention efforts
#
# eCRM Ontology Properties Used:
# - ecrm-ontology:Order (class)
# - ecrm-ontology:hasCompany (property linking Order to Company)
# - ecrm-ontology:orderDate (property for order timestamp)
# - ecrm-ontology:hasAccountManager (property linking Company to Account Manager)
# - ecrm-ontology:hasStage (property for customer lifecycle stage)
#
# Duration Syntax (xsd:duration):
# - P2Y = 2 years
# - P1Y = 1 year
# - P6M = 6 months
# - P90D = 90 days
# - P30D = 30 days
#
# Common Use Cases:
# - Customer retention analysis
# - Re-engagement campaign targeting
# - Account health monitoring
# - Churn prediction and prevention
# - Sales pipeline management
#
## ==============================================================================