1. 结果处理基础 #
RETURN子句不仅可以返回节点和属性,还可以返回表达式、函数结果等。同时,我们还可以对结果进行去重、限制数量、排序等操作。
1.1 返回表达式和别名 #
// 清空数据库
MATCH (n) DETACH DELETE n
// 创建测试数据
CREATE (p1:Person {name: "张三", age: 30, city: "北京"}),
(p2:Person {name: "李四", age: 25, city: "上海"}),
(p3:Person {name: "王五", age: 15, city: "广州"}),
(p4:Person {name: "赵六", age: 65, city: "深圳"}),
(c1:Company {name: "科技公司"}),
(c2:Company {name: "互联网公司"})
CREATE (p1)-[:WORKS_FOR]->(c1),
(p2)-[:WORKS_FOR]->(c2)
MATCH (p1:Person {name: "张三"}), (c1:Company {name: "科技公司"})
SET p1.salary = 10000
MATCH (p2:Person {name: "李四"}), (c2:Company {name: "互联网公司"})
SET p2.salary = 12000
// 返回计算表达式
MATCH (p:Person)
RETURN p.name, p.age, p.age + 10 AS age_in_10_years
// 使用别名使结果更易读
MATCH (p:Person)
RETURN p.name AS 姓名, p.age AS 年龄, p.city AS 城市
// 返回字符串拼接
MATCH (p:Person)
RETURN p.name + " (" + toString(p.age) + "岁)" AS person_info
// 返回条件表达式
MATCH (p:Person)
RETURN p.name,
CASE
WHEN p.age < 18 THEN "未成年"
WHEN p.age < 60 THEN "成年人"
ELSE "老年人"
END AS age_group
// 返回多个表达式
MATCH (p:Person)-[:WORKS_FOR]->(c:Company)
RETURN p.name AS employee, c.name AS company,
p.salary * 12 AS annual_salary1.2 返回唯一结果(DISTINCT) #
// 清空数据库
MATCH (n) DETACH DELETE n
// 创建测试数据
CREATE (p1:Person {name: "张三", city: "北京"}),
(p2:Person {name: "李四", city: "上海"}),
(p3:Person {name: "王五", city: "北京"}),
(p4:Person {name: "赵六", city: "北京"}),
(m1:Movie {title: "长津湖"}),
(m2:Movie {title: "满江红"}),
(g1:Genre {name: "动作"}),
(g2:Genre {name: "剧情"})
CREATE (p1)-[:IS_FRIENDS_WITH]->(p2),
(p2)-[:IS_FRIENDS_WITH]->(p3),
(m1)-[:BELONGS_TO]->(g1),
(m2)-[:BELONGS_TO]->(g1),
(m1)-[:BELONGS_TO]->(g2)
// 返回所有不同的城市(去重)
MATCH (p:Person)
RETURN DISTINCT p.city AS city
// 返回所有不同的电影类型
MATCH (m:Movie)-[:BELONGS_TO]->(g:Genre)
RETURN DISTINCT g.name AS genre
// 查找所有不同的朋友关系对(避免重复)
MATCH (p1:Person)-[:IS_FRIENDS_WITH]->(p2:Person)
RETURN DISTINCT p1.name AS person1, p2.name AS person2
// 返回所有不同的标签组合
MATCH (p:Person)
RETURN DISTINCT labels(p) AS person_labels
// 对比:不使用 DISTINCT 会返回重复结果
MATCH (p:Person)
RETURN p.city
// 可能返回:北京、上海、北京、北京...
// 使用 DISTINCT 去重
MATCH (p:Person)
RETURN DISTINCT p.city
// 返回:北京、上海...1.3 限制结果数量(LIMIT) #
// 清空数据库
MATCH (n) DETACH DELETE n
// 创建测试数据
CREATE (p1:Person {name: "张三", age: 30}),
(p2:Person {name: "李四", age: 25}),
(p3:Person {name: "王五", age: 20}),
(p4:Person {name: "赵六", age: 35}),
(p5:Person {name: "孙七", age: 28}),
(m1:Movie {title: "长津湖", rating: 9.5}),
(m2:Movie {title: "满江红", rating: 8.5}),
(m3:Movie {title: "功夫", rating: 8.0}),
(m4:Movie {title: "我和我的祖国", rating: 9.0}),
(m5:Movie {title: "流浪地球", rating: 7.5})
CREATE (p1)-[:IS_FRIENDS_WITH]->(p2),
(p1)-[:IS_FRIENDS_WITH]->(p3),
(p2)-[:IS_FRIENDS_WITH]->(p4),
(p3)-[:IS_FRIENDS_WITH]->(p5),
(p4)-[:IS_FRIENDS_WITH]->(p5)
// 只返回前10个人
MATCH (p:Person)
RETURN p.name
LIMIT 10
// 返回前5部评分最高的电影
MATCH (m:Movie)
RETURN m.title, m.rating
ORDER BY m.rating DESC
LIMIT 5
// 返回前3个最年轻的人
MATCH (p:Person)
RETURN p.name, p.age
ORDER BY p.age ASC
LIMIT 3
// 查找前20个有最多朋友的人
MATCH (p:Person)-[:IS_FRIENDS_WITH]->(friend:Person)
RETURN p.name, count(friend) AS friend_count
ORDER BY friend_count DESC
LIMIT 201.4 排序(ORDER BY) #
// 清空数据库
MATCH (n) DETACH DELETE n
// 创建测试数据
CREATE (p1:Person {name: "张三", age: 30, salary: 10000}),
(p2:Person {name: "李四", age: 25, salary: 12000}),
(p3:Person {name: "王五", age: 35, salary: 15000}),
(m1:Movie {title: "长津湖", rating: 9.5}),
(m2:Movie {title: "满江红", rating: 8.5}),
(m3:Movie {title: "功夫", rating: 8.0})
// 按年龄升序排序
MATCH (p:Person)
RETURN p.name, p.age
ORDER BY p.age ASC
// 按年龄降序排序
MATCH (p:Person)
RETURN p.name, p.age
ORDER BY p.age DESC
// 按多个字段排序(先按年龄,再按薪资)
MATCH (p:Person)
RETURN p.name, p.age, p.salary
ORDER BY p.age ASC, p.salary DESC
// 按评分降序排序电影
MATCH (m:Movie)
RETURN m.title, m.rating
ORDER BY m.rating DESC1.5 分页(SKIP 和 LIMIT) #
// 清空数据库
MATCH (n) DETACH DELETE n
// 创建测试数据
CREATE (p1:Person {name: "张三", age: 30}),
(p2:Person {name: "李四", age: 25}),
(p3:Person {name: "王五", age: 20}),
(p4:Person {name: "赵六", age: 35}),
(p5:Person {name: "孙七", age: 28}),
(p6:Person {name: "周八", age: 32}),
(p7:Person {name: "吴九", age: 27}),
(p8:Person {name: "郑十", age: 29})
// 分页查询:第1页(每页3条)
MATCH (p:Person)
RETURN p.name, p.age
ORDER BY p.age
SKIP 0 LIMIT 3
// 分页查询:第2页(每页3条)
MATCH (p:Person)
RETURN p.name, p.age
ORDER BY p.age
SKIP 3 LIMIT 3
// 分页查询:第3页(每页3条)
MATCH (p:Person)
RETURN p.name, p.age
ORDER BY p.age
SKIP 6 LIMIT 32. 聚合函数 #
聚合函数用于对一组数据进行计算,比如计算总数、平均值、最大值、最小值等。
2.1 前置知识:聚合函数 #
聚合函数是对一组值进行计算并返回单个值的函数。常见的聚合函数包括:
- count():计算数量
- sum():求和
- avg():计算平均值
- min():找最小值
- max():找最大值
- collect():收集值到列表
2.2 计算总数(count) #
// 清空数据库
MATCH (n) DETACH DELETE n
// 创建测试数据
CREATE (p1:Person {name: "张三"}),
(p2:Person {name: "李四"}),
(p3:Person {name: "王五"}),
(m1:Movie {title: "长津湖"}),
(m2:Movie {title: "满江红"}),
(c1:Company {name: "科技公司"})
CREATE (p1)-[:IS_FRIENDS_WITH]->(p2),
(p1)-[:IS_FRIENDS_WITH]->(p3),
(p1)-[:ACTED_IN]->(m1),
(p2)-[:ACTED_IN]->(m1),
(p3)-[:ACTED_IN]->(m1),
(p1)-[:WORKS_FOR]->(c1),
(p2)-[:WORKS_FOR]->(c1)
// 计算总共有多少人
MATCH (p:Person)
RETURN count(p) AS total_people
// 计算总共有多少部电影
MATCH (m:Movie)
RETURN count(m) AS total_movies
// 计算某个人的朋友数量
MATCH (p:Person {name: "张三"})-[:IS_FRIENDS_WITH]->(friend:Person)
RETURN count(friend) AS friend_count
// 计算参演某部电影的演员数量
MATCH (m:Movie {title: "长津湖"})<-[:ACTED_IN]-(a:Person)
RETURN count(a) AS actor_count
// 计算有工作关系的人的数量
MATCH (p:Person)-[:WORKS_FOR]->()
RETURN count(DISTINCT p) AS employed_count2.3 求和(sum) #
// 清空数据库
MATCH (n) DETACH DELETE n
// 创建测试数据
CREATE (p1:Person {name: "张三", salary: 10000}),
(p2:Person {name: "李四", salary: 12000}),
(p3:Person {name: "王五", salary: 15000}),
(c1:Company {name: "科技公司"}),
(c2:Company {name: "互联网公司"})
CREATE (p1)-[:WORKS_FOR]->(c1),
(p2)-[:WORKS_FOR]->(c1),
(p3)-[:WORKS_FOR]->(c2)
// 计算所有人的薪资总和
MATCH (p:Person)
RETURN sum(p.salary) AS total_salary
// 计算每个公司的薪资总和
MATCH (p:Person)-[:WORKS_FOR]->(c:Company)
RETURN c.name AS company, sum(p.salary) AS total_salary2.4 平均值(avg) #
// 清空数据库
MATCH (n) DETACH DELETE n
// 创建测试数据
CREATE (p1:Person {name: "张三", age: 30, score: 85}),
(p2:Person {name: "李四", age: 25, score: 90}),
(p3:Person {name: "王五", age: 35, score: 95}),
(c1:Course {name: "数学"}),
(c2:Course {name: "英语"})
CREATE (p1)-[:TAKES]->(c1),
(p2)-[:TAKES]->(c1),
(p3)-[:TAKES]->(c1)
// 计算平均年龄
MATCH (p:Person)
RETURN avg(p.age) AS average_age
// 计算平均分数
MATCH (p:Person)
RETURN avg(p.score) AS average_score
// 计算每门课程的平均分
MATCH (c:Course)<-[:TAKES]-(p:Person)
RETURN c.name, avg(p.score) AS average_score2.5 最小值和最大值(min 和 max) #
// 清空数据库
MATCH (n) DETACH DELETE n
// 创建测试数据
CREATE (p1:Person {name: "张三", age: 30}),
(p2:Person {name: "李四", age: 25}),
(p3:Person {name: "王五", age: 35}),
(c1:Company {name: "科技公司"}),
(c2:Company {name: "互联网公司"})
CREATE (p1)-[:WORKS_FOR]->(c1),
(p2)-[:WORKS_FOR]->(c1),
(p3)-[:WORKS_FOR]->(c2)
// 查找最小年龄和最大年龄
MATCH (p:Person)
RETURN min(p.age) AS min_age, max(p.age) AS max_age
// 统计每个公司的年龄范围
MATCH (c:Company)<-[:WORKS_FOR]-(p:Person)
RETURN c.name, min(p.age) AS min_age, max(p.age) AS max_age2.6 收集到列表(collect) #
// 清空数据库
MATCH (n) DETACH DELETE n
// 创建测试数据
CREATE (p1:Person {name: "张三"}),
(p2:Person {name: "李四"}),
(p3:Person {name: "王五"}),
(m1:Movie {title: "长津湖"}),
(m2:Movie {title: "满江红"}),
(c1:Company {name: "科技公司"})
CREATE (p1)-[:IS_FRIENDS_WITH]->(p2),
(p1)-[:IS_FRIENDS_WITH]->(p3),
(p1)-[:ACTED_IN]->(m1),
(p2)-[:ACTED_IN]->(m1),
(p1)-[:ACTED_IN]->(m2)
// 收集某个人的所有朋友的名字到列表中
MATCH (p:Person {name: "张三"})-[:IS_FRIENDS_WITH]->(friend:Person)
RETURN p.name, collect(friend.name) AS friends
// 收集参演某部电影的所有演员名字
MATCH (m:Movie {title: "长津湖"})<-[:ACTED_IN]-(a:Person)
RETURN m.title, collect(a.name) AS actors
// 收集每个人参演的所有电影
MATCH (a:Person)-[:ACTED_IN]->(m:Movie)
RETURN a.name AS actor, collect(m.title) AS movies
// 收集每个城市的所有人
MATCH (p:Person)
RETURN p.city, collect(p.name) AS people2.7 分组聚合 #
// 清空数据库
MATCH (n) DETACH DELETE n
// 创建测试数据
CREATE (p1:Person {name: "张三", age: 30, city: "北京"}),
(p2:Person {name: "李四", age: 25, city: "上海"}),
(p3:Person {name: "王五", age: 20, city: "北京"}),
(p4:Person {name: "赵六", age: 35, city: "上海"}),
(p5:Person {name: "孙七", age: 45, city: "广州"}),
(m1:Movie {title: "长津湖"}),
(m2:Movie {title: "满江红"}),
(m3:Movie {title: "功夫"}),
(g1:Genre {name: "动作"}),
(g2:Genre {name: "剧情"}),
(c1:Company {name: "科技公司"}),
(c2:Company {name: "互联网公司"})
CREATE (p1)-[:WORKS_FOR]->(c1),
(p2)-[:WORKS_FOR]->(c1),
(p3)-[:WORKS_FOR]->(c2),
(p1)-[:DIRECTED]->(m1),
(p1)-[:DIRECTED]->(m2),
(p2)-[:DIRECTED]->(m3),
(m1)-[:BELONGS_TO]->(g1),
(m2)-[:BELONGS_TO]->(g1),
(m3)-[:BELONGS_TO]->(g2)
// 按城市分组,统计每个城市的人数
MATCH (p:Person)
RETURN p.city AS city, count(p) AS population
ORDER BY population DESC
// 按电影类型分组,统计每种类型的电影数量
MATCH (m:Movie)-[:BELONGS_TO]->(g:Genre)
RETURN g.name AS genre, count(m) AS movie_count
// 按公司分组,统计每个公司的员工数量
MATCH (p:Person)-[:WORKS_FOR]->(c:Company)
RETURN c.name AS company, count(p) AS employee_count
// 按年龄分组,统计每个年龄段的人数
MATCH (p:Person)
RETURN
CASE
WHEN p.age < 20 THEN "20岁以下"
WHEN p.age < 30 THEN "20-29岁"
WHEN p.age < 40 THEN "30-39岁"
ELSE "40岁以上"
END AS age_group,
count(p) AS count
// 按导演分组,统计每个导演执导的电影数量
MATCH (d:Person)-[:DIRECTED]->(m:Movie)
RETURN d.name AS director, count(m) AS movie_count
ORDER BY movie_count DESC3. 小结 #
3.1 核心概念 #
| 概念 | 说明 | 主要用途 |
|---|---|---|
| DISTINCT | 去重 | 返回唯一的结果 |
| LIMIT | 限制数量 | 限制返回的结果数量 |
| SKIP | 跳过结果 | 分页查询时跳过前面的结果 |
| ORDER BY | 排序 | 按指定字段排序结果 |
| count() | 计数 | 计算数量 |
| sum() | 求和 | 计算总和 |
| avg() | 平均值 | 计算平均值 |
| min() | 最小值 | 找最小值 |
| max() | 最大值 | 找最大值 |
| collect() | 收集 | 收集值到列表 |
3.2 最佳实践 #
- 使用DISTINCT去重:当结果可能重复时,使用DISTINCT去除重复
- 使用LIMIT限制结果:当结果很多时,使用LIMIT避免返回过多数据
- 使用ORDER BY排序:让结果更有意义,便于查看
- 使用聚合函数:对数据进行统计分析
- 使用分组聚合:按某个字段分组,然后对每组进行聚合计算
3.3 常见用法 #
- 使用DISTINCT去除重复结果
- 使用LIMIT限制大型查询结果
- 使用ORDER BY对结果排序
- 使用SKIP和LIMIT实现分页
- 使用聚合函数进行统计分析
- 使用分组聚合按字段分组统计