Neo4j图数据库:扩展单层股东查询至指定层级(含日期过滤)
扩展Neo4j多层股东查询实现
数据库结构说明
- 节点类型:
Person(自然人)、Company(公司) - 关系类型:
Shareholder(持股关系,支持自然人→公司、公司→公司) - 关系属性:
shareholding_start_date:持股起始日期shareholding_end_date:持股结束日期number_of_shares:持股数量
现有查询功能
输入目标公司名称与指定日期,返回该日期下目标公司的直接股东及对应持股百分比,原查询代码如下:
MATCH (c:Company {name:"ABC"})<-[r:Shareholder]-(s) WHERE r.shareholding_start_date <= Date("2021-07-23") AND r.shareholding_end_date >= DATE("2021-07-23") WITH c, collect(s) as shareholders, collect(r) as rels, sum(r.number_of_shares) AS totalShares UNWIND range(0, size(rels) - 1) AS i RETURN shareholders[i].name AS shareholder, 100.0 * rels[i].number_of_shares/totalShares as percentTotalShares
扩展需求
支持指定层级(如3层)的股东查询:不仅返回目标公司的直接股东,还需递归查询股东的股东,直至达到设定的层级限制,同时计算每个股东的累计持股百分比(间接持股按路径比例相乘后累加)。
扩展后的查询代码
以下代码支持指定层级(示例为3层)、目标公司名称("ABC")和查询日期("2021-07-23"):
// 定义参数,可根据需求修改 :param targetCompany => "ABC"; :param queryDate => Date("2021-07-23"); :param maxLevel => 3; // 匹配从股东到目标公司的多层路径,层级范围1到maxLevel MATCH path = (shareholder)-[rels:Shareholder*1..$maxLevel]->(target:Company {name: $targetCompany}) // 过滤路径中每一层持股关系都在查询日期有效 WHERE ALL(r IN rels WHERE r.shareholding_start_date <= $queryDate AND r.shareholding_end_date >= $queryDate) // 计算目标公司在查询日期的总股份数 WITH path, shareholder, rels, target MATCH (target)<-[rTotal:Shareholder]-() WHERE rTotal.shareholding_start_date <= $queryDate AND rTotal.shareholding_end_date >= $queryDate WITH shareholder, rels, sum(rTotal.number_of_shares) AS targetTotalShares // 计算每条路径的累计持股比例:每层持股数/对应公司总股份 相乘 WITH shareholder, reduce(accumulatedPercent = 1.0, r IN rels | let currentCompany = endNode(r), // 获取当前关系指向公司的同期总股份 currentCompanyTotal = (MATCH (currentCompany)<-[rCurr:Shareholder]-() WHERE rCurr.shareholding_start_date <= $queryDate AND rCurr.shareholding_end_date >= $queryDate RETURN sum(rCurr.number_of_shares) AS total), accumulatedPercent * (r.number_of_shares / currentCompanyTotal) ) AS pathPercent // 按股东分组,累加所有路径的持股比例,转换为百分比 WITH shareholder.name AS shareholderName, sum(pathPercent) * 100 AS totalPercent // 排序输出,保留两位小数 RETURN shareholderName, round(totalPercent, 2) AS percentTotalShares ORDER BY totalPercent DESC
关键说明
- 使用
[rels:Shareholder*1..$maxLevel]指定递归查询的层级范围(1到设定的最大层级) ALL(r IN rels WHERE ...)确保路径中每一层的持股关系在查询日期都处于有效状态- 通过
reduce函数递归计算每条路径的累计持股比例(间接持股为各层比例的乘积) - 按股东分组后累加所有路径的比例,得到该股东对目标公司的总持股百分比
- 参数化设计方便快速修改目标公司、查询日期和最大层级
内容的提问来源于stack exchange,提问作者Programmer
相关产品推荐
相关产品推荐

