首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >本体推理查询语言SPARQL 从入门到精通

本体推理查询语言SPARQL 从入门到精通

作者头像
本体与AI
发布2026-09-09 20:43:35
发布2026-09-09 20:43:35
100
举报

SPARQL 完全入门教程

本教程面向零基础学习者,从 SELECT 到 CONSTRUCT,从 FILTER 到 Property Path,覆盖 SPARQL 所有核心功能。所有示例都可以直接在 Fuseki Web UI 中运行。

1. 什么是 SPARQL

SPARQL(读作「sparkle」,字面意思「闪亮」)是 RDF 数据的查询语言,就像 SQL 是关系数据库的查询语言一样。

概念

SQL 对应

SPARQL 对应

Row

三元组 (s, p, o)

Table

RDF Graph

Column

属性 (Property)

查询

SELECT ... FROM ... WHERE

SELECT ... WHERE { ... }

过滤

WHERE age > 18

FILTER (?age > 18)

连接

JOIN

共用变量(自动 INNER JOIN)

左连接

LEFT JOIN

OPTIONAL { }

代码语言:javascript
复制
SELECT ?name ?age
WHERE {
  ?person :hasName ?name .
  ?person :hasAge ?age .
}

核心思想

SPARQL 本质就是模式匹配:你给一个图模式(Graph Pattern),引擎在图里找到所有匹配的部分,把绑定告诉你就行。

2. 基础结构 基础

每条 SPARQL 查询由三部分组成:

代码语言:javascript
复制
PREFIX 短名: <URL>          # 前缀声明
SELECT ?变量1 ?变量2        # 返回哪些列
WHERE {                     # 匹配条件
  三元组模式
}

2.1 前缀(PREFIX)

RDF 中所有资源都用完整 URL 标识,前缀让这些 URL 可读:

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>

常见错误

Fuseki 不会自动加前缀。用了 rdfs:label 就必须写 PREFIX rdfs:,否则报 Unresolved prefixed name。

2.2 变量

SPARQL 变量以 ? 或 $ 开头,习惯用问号:

代码语言:javascript
复制
?employee ?leave  ?days  ?status

2.3 最简单的查询:查所有

代码语言:javascript
复制
SELECT *
WHERE {
  ?s ?p ?o .
}
LIMIT 10

实践技巧

数据量大的时候一定要加 LIMIT,否则浏览器会卡死,服务器也可能超时。

3. 三元组模式匹配 基础

SPARQL 的核心 —— 构造图模式,引擎在 RDF 图中找到匹配的子图。

3.1 查某一个人的所有信息

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>

SELECT ?p ?o
WHERE {
  :Emp_Zhao ?p ?o .
}

输出:赵工程师的所有属性和值(rdf:type、:salary、:reportsTo 等)。

3.2 多条件匹配(隐含 JOIN)

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?name ?salary ?deptName
WHERE {
  ?e rdfs:label ?name .
  ?e :salary ?salary .
  ?e :belongsTo ?dept .
  ?dept :departmentName ?deptName .
}

这里四个三元组模式共享变量 ?e,引擎会自动做 JOIN。

3.3 查所有请假申请

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?empName ?days ?status
WHERE {
  ?l a :LeaveRequest ;
     :requestedBy ?e ;
     :leaveDays ?days ;
     :leaveStatus ?status .
  ?e rdfs:label ?empName .
}
ORDER BY ?status ?days

分号简写

?l a :LeaveRequest ; :requestedBy ?e ; :leaveDays ?days 等价于三条语句,主语都是 ?l。

4. FILTER 过滤 基础

FILTER 筛选结果,写在大括号内。

4.1 数值比较

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?name ?salary
WHERE {
  ?e rdfs:label ?name ;
     :salary ?salary .
FILTER (?salary > 20000)
}
ORDER BYDESC(?salary)

4.2 字符串匹配

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?name ?salary
WHERE {
  ?e rdfs:label ?name ;
     :salary ?salary .
FILTER(regex(str(?name), "工程师"))
}

4.3 逻辑组合

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?name ?salary ?deptName
WHERE {
  ?e rdfs:label ?name ;
     :salary ?salary ;
     :belongsTo ?dept .
  ?dept :departmentName ?deptName .
FILTER (
    ?salary >= 15000 &&
    ?salary <= 20000 &&
    ?deptName != "销售部"@zh
  )
}

4.4 常用 FILTER 函数速查

函数

示例

说明

比较

FILTER (?x > 5)

> < >= <= = !=

逻辑

FILTER (?a && !?b)

&& || !

字符串

FILTER regex(str(?n), "^张")

正则匹配

类型检查

FILTER isURI(?x)

isURI / isLiteral / isBlank

存在检查

FILTER bound(?y)

变量是否有绑定

IN 集合

FILTER (?x IN (1, 2, 3))

是不是列表中的值

语言标签

FILTER lang(?name) = "zh"

按语言筛选

5. OPTIONAL 可选匹配 进阶

类似于 SQL 的 LEFT JOIN。如果匹配不到,变量为 unbound(空),不会过滤掉这一行。

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?name ?leaveLabel ?days
WHERE {
  ?e rdfs:label ?name .
OPTIONAL {
    ?l :requestedBy ?e ;
       rdfs:label ?leaveLabel ;
       :leaveDays ?days .
  }
}

结果:所有员工都会显示,没有请假的员工 leaveLabel 和 days 为空。

代码语言:javascript
复制
FILTER (!bound(?leaveLabel))   # 找出没有请假记录的员工

6. UNION 联合查询 进阶

合并多个模式的匹配结果,类似于 SQL 的 UNION ALL。

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?name ?typeLabel
WHERE {
  { ?e a :Manager ; rdfs:label ?name . BIND("Manager" AS ?typeLabel) }
UNION
  { ?e a :HRStaff ; rdfs:label ?name . BIND("HR" AS ?typeLabel) }
UNION
  { ?e :salary ?s ; rdfs:label ?name . FILTER (?s >= 30000) BIND("高薪" AS ?typeLabel) }
}

7. Property Path 属性路径 高级

这是 SPARQL 最强大的功能之一,可以沿着属性路径进行图遍历。

语法

含义

示例

:reportsTo ?m

一步到达

直接上级

:reportsTo+ ?m

一步或多步

所有上级(传递闭包)

:reportsTo* ?m

零步或多步

自己 + 所有上级

:reportsTo{1,3}

1~3 步

三级以内上级

^:reportsTo ?m

反向

找下属

:p1|:p2 ?o

或(两种路径任选一)

取 p1 或 p2

:p1/:p2 ?o

串联(先 p1 再 p2)

走两步

7.1 查赵工程师的所有上级

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?name ?level
WHERE {
  :Emp_Zhao :reportsTo+ ?mgr .
  ?mgr rdfs:label ?name .
}

7.2 查王经理的所有下属(反向路径)

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?name
WHERE {
  ?emp ^:reportsTo+ :TechMgr_Wang .
  ?emp rdfs:label ?name .
}

7.3 查 CEO 可批准的所有请假

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?leaver ?leaveLabel ?days
WHERE {
  ?l :requestedBy ?e .
  ?e :reportsTo+ :CEO_Zhang .
  ?e rdfs:label ?leaver .
  ?l rdfs:label ?leaveLabel ;
     :leaveDays ?days .
}

8. 聚合查询 进阶

8.1 COUNT — 统计各部门员工数

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?deptName (COUNT(?e) AS ?count)
WHERE {
  ?e :belongsTo ?dept .
  ?dept :departmentName ?deptName .
}
GROUP BY ?deptName
ORDER BYDESC(?count)

8.2 SUM、AVG、MIN、MAX — 统计假期

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>

SELECT
  (SUM(?days) AS ?totalDays)
  (AVG(?days) AS ?avgDays)
  (MAX(?days) AS ?maxDays)
  (MIN(?days) AS ?minDays)
WHERE {
  ?l :leaveDays ?days .
}

8.3 HAVING — 聚合后过滤

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?empName (SUM(?days) AS ?totalDays)
WHERE {
  ?l :requestedBy ?e ;
     :leaveDays ?days .
  ?e rdfs:label ?empName .
}
GROUP BY ?empName
HAVING (SUM(?days) > 20)
ORDER BYDESC(?totalDays)

9. ORDER BY、LIMIT、OFFSET 基础

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?name ?salary
WHERE {
  ?e rdfs:label ?name ;
     :salary ?salary .
}
ORDER BYDESC(?salary)   # DESC 降序,ASC 升序
LIMIT 3                       # 只取前三
OFFSET 1                     # 跳过第一条(分页第二页)

分页公式

LIMIT ?pageSize OFFSET ((?page - 1) * ?pageSize) —— 但 SPARQL 不支持表达式作为 LIMIT/OFFSET 参数,只能写常数。

10. CONSTRUCT 构造新数据 进阶

CONSTRUCT 不是返回表格,而是构造新的 RDF 三元组。适合做数据转换或导出推理结果。

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

CONSTRUCT {
  ?e :needApproval :CEO_Zhang .
}
WHERE {
  ?l :requestedBy ?e ;
     :leaveDays ?days .
FILTER (?days > 10)
}

执行后 Fuseki 会返回构造出的 RDF(可切换 TTL / RDF/XML 格式查看)。

11. ASK & DESCRIBE 基础

ASK — 问「有没有」

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>

ASK {
  :CEO_Zhang a :Manager .
}

返回 true 或 false。一个 boolean,不是表格。

DESCRIBE — 描述一个资源

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>

DESCRIBE :Emp_Zhao

返回关于 :Emp_Zhao 的所有已知三元组(具体返回什么由服务端决定,不是标准化的)。

12. INSERT / DELETE 数据更新 进阶

注意

INSERT/DELETE 是 SPARQL Update,必须在 Fuseki 的 UPDATE 端点(/ds/update)执行,不是在 QUERY 端点。

INSERT DATA

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

INSERT DATA {
  :Emp_NewUser a :Employee ;
               :employeeId "E099" ;
               :salary 18000 ;
               :reportsTo :TechMgr_Wang ;
               :belongsTo :DeptTech ;
               rdfs:label "新员工"@zh .
}

DELETE DATA

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

DELETE DATA {
  :Emp_NewUser rdfs:label "新员工"@zh .
}

INSERT WHERE(先查后插)

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>

INSERT {
  ?l :needsCEOApproval true .
}
WHERE {
  ?l a :LeaveRequest ;
     :leaveDays ?days .
FILTER (?days > 10)
}

DELETE WHERE(删除匹配的数据)

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>

DELETE WHERE {
  :Emp_NewUser ?p ?o .
}

13. BIND、VALUES、子查询 进阶

BIND — 计算新值

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?name ?monthlySalary ?annualSalary
WHERE {
  ?e rdfs:label ?name ;
     :salary ?monthlySalary .
BIND (?monthlySalary * 12 AS ?annualSalary)
}

VALUES — 枚举值(模拟 IN 操作)

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?name ?salary
WHERE {
VALUES ?dept { :DeptTech :DeptHR }
  ?e :belongsTo ?dept ;
     rdfs:label ?name ;
     :salary ?salary .
}

子查询

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?name ?salary
WHERE {
SELECT ?e (AVG(?s) AS ?avgSalary)
WHERE {
    ?e :belongsTo :DeptTech ;
       :salary ?s .
  }
  ?e rdfs:label ?name ;
     :salary ?salary .
FILTER (?salary > ?avgSalary)
}

14. 实战综合练习 练习

基于公司请假数据,以下是可以直接复制到 Fuseki 运行的 8 个实战查询。

练习1:查技术研发部所有员工

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?name ?salary
WHERE {
  ?e :belongsTo :DeptTech ;
     rdfs:label ?name ;
     :salary ?salary .
}
ORDER BYDESC(?salary)

练习2:每人请假总天数和次数

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?empName
       (COUNT(?l) AS ?leaveCount)
       (SUM(?days) AS ?totalDays)
WHERE {
  ?l :requestedBy ?e ;
     :leaveDays ?days .
  ?e rdfs:label ?empName .
}
GROUP BY ?empName
ORDER BYDESC(?totalDays)

练习3:查 pending or approved 的请假,标注风险

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?empName ?leaveLabel ?days ?risk
WHERE {
  ?l :requestedBy ?e ;
     :leaveDays ?days ;
     rdfs:label ?leaveLabel ;
     :leaveStatus ?status .
  ?e rdfs:label ?empName .
BIND (
IF(?days > 10, "高风险",
IF(?days > 5, "中风险",
"低风险")
    ) AS ?risk
  )
FILTER (?status = "pending"@en || ?status = "approved"@en)
}
ORDER BYDESC(?days)

练习4:查褚销售的上上级

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?name ?hop
WHERE {
  :Sales_Emp_Chu :reportsTo+ ?mgr .
BIND ("上级"@zh AS ?hop)
  ?mgr rdfs:label ?name .
}

练习5:各部门请假天数汇总

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>

SELECT ?deptName
       (COUNT(?l) AS ?count)
       (SUM(?days) AS ?total)
       (ROUND(AVG(?days)*10)/10 AS ?avg)
WHERE {
  ?l :requestedBy ?e ;
     :leaveDays ?days .
  ?e :belongsTo ?dept .
  ?dept :departmentName ?deptName .
}
GROUP BY ?deptName
ORDER BYDESC(?total)

练习6:CONSTRUCT 构造“谁批准了谁”关系

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

CONSTRUCT {
  ?approver :approvedLeaveOf ?leaver .
}
WHERE {
  ?l :approvedBy ?approver ;
     :requestedBy ?leaver .
}

练习7:查所有「指定人已请假」的冲突日期

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>

SELECT ?empName ?leaveLabel ?start ?end ?days
WHERE {
  ?l :requestedBy ?e ;
     :startDate ?start ;
     :endDate ?end ;
     :leaveDays ?days ;
     rdfs:label ?leaveLabel .
  ?e rdfs:label ?empName .
# 查 7 月有请假的(startDate 或 endDate 在 7 月内)
FILTER (
    (?start >= "2026-07-01"^^xsd:date && ?start <= "2026-07-31"^^xsd:date) ||
    (?end   >= "2026-07-01"^^xsd:date && ?end   <= "2026-07-31"^^xsd:date)
  )
}
ORDER BY ?start

练习8:用 COALESCE 合并可能为空的字段

代码语言:javascript
复制
PREFIX : <http://example.org/company-leave#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

SELECT ?empName ?leaveLabel
       (COALESCE(?approverName, "待审批"@zh) AS ?approver)
WHERE {
  ?l :requestedBy ?e ;
     rdfs:label ?leaveLabel .
  ?e rdfs:label ?empName .
OPTIONAL {
    ?l :approvedBy ?p .
    ?p rdfs:label ?approverName .
  }
}

15. 常见错误速查

错误信息

原因

修正

Unresolved prefixed name: rdfs:label

忘了声明 PREFIX rdfs

在查询最前面加 PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>

Parse error: Encountered " "..." at line X

语法错误(缺括号/句号/引号)

检查每一行末尾的 . 和括号匹配

No such property: xxx

查询了不存在的属性

用 SELECT ?p WHERE { ?s ?p ?o } 先看有哪些属性

查询返回空

数据没加载 / FILTER 太严格 / 类型不匹配

先跑 SELECT * WHERE { ?s ?p ?o } LIMIT 10 确认有数据

GROUP BY 后选错了列

SELECT 了非聚合非分组的变量

非聚合列必须出现在 GROUP BY 里

INSERT 不生效

在 query 端点发了 UPDATE 语句

切到 Fuseki 的 update 端点,或 Web UI 点 "update" 标签

调试三部曲

1. SELECT * WHERE { ?s ?p ?o } LIMIT 10 —— 确认数据在 2. SELECT ?s ?p ?o WHERE { :已知资源 ?p ?o } —— 缩小范围看资源 3. 逐步加条件,每加一个就测一次 —— 定位哪个条件过滤掉了结果


速查卡片

代码语言:javascript
复制
SELECT * WHERE { ?s ?p ?o } LIMIT 100

SPARQL 完全入门教程 — 所有示例基于公司请假数据集 — 直接在 Fuseki Web UI 中可运行

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-06-17,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • SPARQL 完全入门教程
    • 1. 什么是 SPARQL
    • 2. 基础结构 基础
      • 2.1 前缀(PREFIX)
      • 2.2 变量
      • 2.3 最简单的查询:查所有
    • 3. 三元组模式匹配 基础
      • 3.1 查某一个人的所有信息
      • 3.2 多条件匹配(隐含 JOIN)
      • 3.3 查所有请假申请
    • 4. FILTER 过滤 基础
      • 4.1 数值比较
      • 4.2 字符串匹配
      • 4.3 逻辑组合
      • 4.4 常用 FILTER 函数速查
    • 5. OPTIONAL 可选匹配 进阶
    • 6. UNION 联合查询 进阶
    • 7. Property Path 属性路径 高级
      • 7.1 查赵工程师的所有上级
      • 7.2 查王经理的所有下属(反向路径)
      • 7.3 查 CEO 可批准的所有请假
    • 8. 聚合查询 进阶
      • 8.1 COUNT — 统计各部门员工数
      • 8.2 SUM、AVG、MIN、MAX — 统计假期
      • 8.3 HAVING — 聚合后过滤
    • 9. ORDER BY、LIMIT、OFFSET 基础
    • 10. CONSTRUCT 构造新数据 进阶
    • 11. ASK & DESCRIBE 基础
      • ASK — 问「有没有」
      • DESCRIBE — 描述一个资源
    • 12. INSERT / DELETE 数据更新 进阶
      • INSERT DATA
      • DELETE DATA
      • INSERT WHERE(先查后插)
      • DELETE WHERE(删除匹配的数据)
    • 13. BIND、VALUES、子查询 进阶
      • BIND — 计算新值
      • VALUES — 枚举值(模拟 IN 操作)
      • 子查询
    • 14. 实战综合练习 练习
      • 练习1:查技术研发部所有员工
      • 练习2:每人请假总天数和次数
      • 练习3:查 pending or approved 的请假,标注风险
      • 练习4:查褚销售的上上级
      • 练习5:各部门请假天数汇总
      • 练习6:CONSTRUCT 构造“谁批准了谁”关系
      • 练习7:查所有「指定人已请假」的冲突日期
      • 练习8:用 COALESCE 合并可能为空的字段
    • 15. 常见错误速查
    • 速查卡片
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档