如何在Datalog查询中对多值属性的去重值求和?
多值属性去重后求和的解决方案
针对Datomic中多值属性求和会重复计算所有Datom的问题,可通过按实体分组并对属性值去重后求和的方式解决,以下是两种实用写法:
方法一:聚合函数嵌套去重
利用Datomic聚合函数支持嵌套distinct的特性,直接在sum中过滤重复值:
[:find (sum (distinct ?int-val)) (sum (distinct ?ii-val)) :where [?e :Ns/ints ?int-val] [?e :Ns/ii ?ii-val] :group-by ?e]
通过:group-by ?e将计算范围限定在单个实体内部,(distinct ?int-val)会过滤当前实体下重复的属性值,再用sum计算去重后的总和。
方法二:先取去重集合再求和
先获取实体的去重属性集合,再对集合执行求和操作,逻辑更直观:
[:find ?e (apply sum (distinct ?ints)) (apply sum (distinct ?iis)) :where [?e :Ns/ints ?ints] [?e :Ns/ii ?iis] :group-by ?e]
原查询出错原因
未按实体分组时,关联查询会生成多值属性的笛卡尔积结果(比如[:Ns/ints 1]分别和[:Ns/ii 1]、[:Ns/ii 2]组合,[:Ns/ints 2]同理,共4条结果),sum会累加所有结果行的数值,最终得到1+1+2+2=6的错误总和。通过:group-by ?e锁定单个实体的计算范围,就能避免重复计算。
内容的提问来源于stack exchange,提问作者Marc Grue
相关产品推荐
相关产品推荐

