COUNT 子查询

一个 COUNT 子查询可以用来计算子查询返回的行数。

示例图

以下图用于下面的示例

subqueries graph

要重新创建该图,请针对空的 Neo4j 数据库运行以下查询

CREATE
(andy:Swedish:Person {name: 'Andy', age: 36}),
(timothy:Person {name: 'Timothy', nickname: 'Tim', age: 25}),
(peter:Person {name: 'Peter', nickname: 'Pete', age: 35}),
(andy)-[:HAS_DOG {since: 2016}]->(:Dog {name:'Andy'}),
(timothy)-[:HAS_CAT {since: 2019}]->(:Cat {name:'Mittens'}),
(fido:Dog {name:'Fido'})<-[:HAS_DOG {since: 2010}]-(peter)-[:HAS_DOG {since: 2018}]->(:Dog {name:'Ozzy'}),
(fido)-[:HAS_TOY]->(:Toy{name:'Banana'})

简单的 COUNT 子查询

外部作用域引入的变量可以在 COUNT 子查询中使用,无需导入。在这方面,COUNT 子查询与 CALL 子查询不同,后者需要导入。以下查询对此进行了说明,并输出拥有超过一只狗的主人

MATCH (person:Person)
WHERE COUNT { (person)-[:HAS_DOG]->(:Dog) } > 1
RETURN person.name AS name
姓名

"Peter"

行数:1

带有 WHERE 子句的 COUNT 子查询

可以在 COUNT 模式内使用 WHERE 子句。MATCH 子句和外部作用域引入的变量可以在此作用域中使用。

MATCH (person:Person)
WHERE COUNT {
  (person)-[:HAS_DOG]->(dog:Dog)
  WHERE person.name = dog.name
} = 1
RETURN person.name AS name
姓名

"Andy"

行数:1

带有 UNIONCOUNT 子查询

COUNT 可以与 UNION 子句一起使用。如果 UNION 子句是 distinct,则需要 RETURN 子句。UNION ALL 子句不需要 RETURN 子句。但是,值得注意的是,如果一个分支具有 RETURN 子句,则所有分支都需要一个。以下示例展示了如何使用 UNION 子句计算每个人拥有的宠物数量

MATCH (person:Person)
RETURN
    person.name AS name,
    COUNT {
        MATCH (person)-[:HAS_DOG]->(dog:Dog)
        RETURN dog.name AS petName
        UNION
        MATCH (person)-[:HAS_CAT]->(cat:Cat)
        RETURN cat.name AS petName
    } AS numPets
姓名 宠物数量

"Andy"

1

"Timothy"

1

"Peter"

2

行数:3

带有 WITHCOUNT 子查询

外部作用域的变量在整个子查询中都是可见的,即使使用 WITH 子句也是如此。为了避免混淆,不允许对这些变量进行隐藏。当在内部作用域中定义的新变量使用相同的变量名时,外部作用域变量会被隐藏。在下面的示例中,外部变量 name 被隐藏,因此会引发错误。

WITH 'Peter' as name
MATCH (person:Person {name: name})
WHERE COUNT {
    WITH "Ozzy" AS name
    MATCH (person)-[:HAS_DOG]->(d:Dog)
    WHERE d.name = name
} = 1
RETURN person.name AS name
错误消息
The variable `name` is shadowing a variable with the same name from the outer scope and needs to be renamed (line 4, column 20 (offset: 90))

只要使用不同的标识符,就可以在子查询中引入新变量。在下面的示例中,WITH 子句引入了新的变量。请注意,在主查询中引用的外部作用域变量 personWITH 子句之后仍然可用。

MATCH (person:Person)
WHERE COUNT {
    WITH "Ozzy" AS dogName
    MATCH (person)-[:HAS_DOG]->(d:Dog)
    WHERE d.name = dogName
} = 1
RETURN person.name AS name
姓名

"Peter"

行数:1

在其他子句中使用 COUNT 子查询

COUNT 可用于查询中的任何位置,管理命令除外,在管理命令中它受到限制。请参见下面的几个示例

RETURN 中使用 COUNT

MATCH (person:Person)
RETURN person.name, COUNT { (person)-[:HAS_DOG]->(:Dog) } as howManyDogs
person.name howManyDogs

"Andy"

1

"Timothy"

0

"Peter"

2

行数:3

SET 中使用 COUNT

MATCH (person:Person) WHERE person.name ="Andy"
SET person.howManyDogs = COUNT { (person)-[:HAS_DOG]->(:Dog) }
RETURN person.howManyDogs as howManyDogs
howManyDogs

1

行数:1
设置的属性:1

CASE 中使用 COUNT

MATCH (person:Person)
RETURN
   CASE
     WHEN COUNT { (person)-[:HAS_DOG]->(:Dog) } > 1 THEN "Doglover " + person.name
     ELSE person.name
   END AS result
结果

"Andy"

"Timothy"

"Doglover Peter"

行数:3

使用 COUNT 作为分组键

以下查询按每个人拥有的狗的数量对所有人进行分组,然后计算每个组的平均年龄。

MATCH (person:Person)
RETURN COUNT { (person)-[:HAS_DOG]->(:Dog) } AS numDogs,
       avg(person.age) AS averageAge
 ORDER BY numDogs
狗的数量 平均年龄

0

25.0

1

36.0

2

35.0

行数:3

带有 RETURNCOUNT 子查询

COUNT 子查询不需要在子查询末尾使用 RETURN 子句。如果存在,则不需要对其进行别名化。这与 CALL 子查询 不同。在 COUNT 子查询中返回的任何变量在子查询之后都不可用。

MATCH (person:Person)
WHERE COUNT {
    MATCH (person)-[:HAS_DOG]->(:Dog)
    RETURN person.name
} = 1
RETURN person.name AS name
姓名

"Andy"

行数:1

规则

以下内容适用于 COUNT 子查询

  • 允许任何非写入查询。

  • 可以省略最后的 RETURN 子句,因为即使使用了最后的 RETURN 子句,在子查询中定义的任何变量在表达式外部都不可用。一个例外是,对于 DISTINCT UNION 子句,RETURN 子句仍然是强制性的。

  • 如果 COUNT 只包含模式和可选的 WHERE 子句,则可以在子查询中省略 MATCH 关键字。

  • COUNT 子查询可以出现在表达式有效的查询中的任何位置。

  • 外部作用域中定义的任何变量都可以在 COUNT 子查询自己的作用域内被引用。

  • COUNT 子查询内部引入的变量不属于外部作用域,因此无法在外部访问。