聚合

更新时间:2025-01-09 07:25:21

通常情况下,聚合函数aggr(expr)会处理每个聚合键在传入记录中找到的所有匹配行(键使用等价性进行比较)。在常规聚合(即形式为aggr(expr)的聚合)中,聚合值列表是候选值列表,并且已从中移除了所有空值。

数据准备

SELECT * FROM cypher('graph_name', $$
 CREATE (a:Person {name: 'A', age: 13}),
 (b:Person {name: 'B', age: 33, eyes: "blue"}),
 (c:Person {name: 'C', age: 44, eyes: "blue"}),
 (d1:Person {name: 'D', eyes: "brown"}),
 (d2:Person {name: 'D'}),
 (a)-[:KNOWS]->(b),
 (a)-[:KNOWS]->(c),
 (a)-[:KNOWS]->(d1),
 (b)-[:KNOWS]->(d2),
 (c)-[:KNOWS]->(d2)
$$) as (a agtype);

自动分组

为了计算聚合数据,Cypher提供聚合功能,类似于SQLGROUP BY

聚合函数接收一组值,并计算这些值的聚合结果。例如,avg函数用于计算多个数值的平均值,min函数用于查找一组值中数值或字符串的最小值。当我们说聚合函数作用于一组值时,指的是这些值是内部表达式(如n.age)应用于同一聚合组内所有记录的结果。

聚合可以在所有匹配的子图上进行计算,也可以通过引入分组键进一步细分。分组键是非聚合表达式,用于对进入聚合函数的值进行分组。

假设存在以下返回语句:

SELECT * FROM cypher('graph_name', $$
    MATCH (v:Person)
    RETURN v.name, count(*)
$$) as (grouping_key agtype, count agtype);

返回结果如下:

 grouping_key | count 
--------------+-------
 "A"          | 1
 "D"          | 2
 "Joan"       | 1
 "B"          | 1
 "John"       | 1
 "Bill"       | 1
 "C"          | 1
 "Jeff"       | 1
(8 rows)

返回中包含两列:grouping_keycount(*)。其中,grouping_key不是聚合函数,因此它将作为分组键。count(*)是一个聚合表达式。匹配的子图将根据分组键被划分成不同的桶。然后,聚合函数将在这些桶上运行,计算每个桶的聚合值。

使用聚合函数排序

使用聚合对结果集进行排序时,该聚合必须包含在RETURN子句中,以便能够在ORDER BY中使用。

SELECT *
FROM cypher('graph_name', $$
    MATCH (me:Person)-[]->(friend:Person)
    RETURN count(friend), me
    ORDER BY count(friend)
$$) as (friends agtype, me agtype);

DISTINCT聚合

DISTINCT聚合(即形式为aggr(DISTINCT expr)的聚合)中,聚合值列表是从候选值列表中移除所有空值后的结果。此外,在DISTINCT聚合中,仅包含一个等价候选值,即在聚合值列表中会去除重复的等价值。

DISTINCT操作符与聚合函数配合使用,用于在将值传递给聚合函数之前,使所有值唯一化。

示例

SELECT *
FROM cypher('graph_name', $$
 MATCH (v:Person)
 RETURN count(DISTINCT v.eyes), count(v.eyes)
$$) as (distinct_eyes agtype, eyes agtype);

返回结果如下:

 distinct_eyes | eyes 
---------------+------
 2             | 3
(1 row)

模糊分组语句

此功能不需要在查询中明确指定分组键,但可能导致Cypher在确定哪些字段应该作为分组键时产生歧义。更多详细信息,请参考社区文档

数据准备

SELECT * FROM cypher('graph_name', $$
CREATE (:L {a: 1, b: 2, c: 3}),
       (:L {a: 2, b: 3, c: 1}),
       (:L {a: 3, b: 1, c: 2})
$$) as (a agtype);

AGE中的无效查询

AGE对于这个问题的解决方案是不允许在WITHRETURN子句中将聚合函数与未在相同WITHRETURN子句的其他列中显式列出的变量组合使用。

示例

SELECT * FROM cypher('graph_name', $$
    MATCH (x:L)
    RETURN x.a + count(*) + x.b + count(*) + x.c
$$) as (a agtype);

返回结果如下:

ERROR:  "x" must be either part of an explicitly listed key or used inside an aggregate function
LINE 3:     RETURN x.a + count(*) + x.b + count(*) + x.c

AGE中的有效查询

AGE中,不包含聚合函数的列被视为该WITHRETURN子句的分组键。

示例

对于上述查询可以使用以下方式重写查询,使其正常返回结果。

  • SELECT * FROM cypher('graph_name', $$
        MATCH (x:L)
        RETURN (x.a + x.b + x.c) + count(*) + count(*), x.a + x.b + x.c
    $$) as (count agtype, key agtype);

    其中,x.a + x.b + x.c 是分组键。此类创建的分组键必须包含括号。

     count | key 
    -------+-----
     12    | 6
    (1 row)
  • SELECT * FROM cypher('graph_name', $$
        MATCH (x:L)
        RETURN x.a + count(*) + x.b + count(*) + x.c, x.a, x.b, x.c
    $$) as (count agtype, a agtype, b agtype, c agtype);

    其中,x.ax.bx.c将被视为不同的分组键。

     count | a | b | c 
    -------+---+---+---
     8     | 3 | 1 | 2
     8     | 2 | 3 | 1
     8     | 1 | 2 | 3
    (3 rows)

模糊分组中的顶点和边

分组键可以是一个顶点或边,然后可以无需在WITH或 RETURN子句中显式指定该顶点或边的任何属性。

示例

SELECT * FROM cypher('graph_name', $$
    MATCH (x:L)
    RETURN count(*) + count(*) + x.a + x.b + x.c, x
$$) as (count agtype, key agtype);

结果将按x分组,因为可以合理假设属性被认为是不必要的,以确保明确分组。

 count |                                          key                                           
-------+----------------------------------------------------------------------------------------
 8     | {"id": 1407374883553283, "label": "L", "properties": {"a": 3, "b": 1, "c": 2}}::vertex
 8     | {"id": 1407374883553281, "label": "L", "properties": {"a": 1, "b": 2, "c": 3}}::vertex
 8     | {"id": 1407374883553282, "label": "L", "properties": {"a": 2, "b": 3, "c": 1}}::vertex
(3 rows)

隐藏不必要的分组键

如果分组键在查询输出中被认为是不必要的,可以在WITH子句中进行聚合,然后将信息传递给RETURN子句。

示例

SELECT * FROM cypher('graph_name', $$
    MATCH (x:L)
    WITH count(*) + count(*) + x.a + x.b + x.c as column, x
    RETURN column
$$) as (a agtype);

返回结果如下:

 a 
---
 8
 8
 8
(3 rows)

  • 本页导读 (1)
  • 数据准备
  • 自动分组
  • 使用聚合函数排序
  • DISTINCT聚合
  • 模糊分组语句
  • 数据准备
  • AGE中的无效查询
  • AGE中的有效查询
  • 模糊分组中的顶点和边
  • 隐藏不必要的分组键
AI助理

点击开启售前

在线咨询服务

你好,我是AI助理

可以解答问题、推荐解决方案等