ClickHouse中表内矩阵逐元素求和的最优高效实现方法
优化ClickHouse矩阵逐元素求和的方案
嘿,我来帮你优化这个矩阵逐元素求和的查询!你的当前方法需要手动指定每个维度的元素,确实不够灵活——要是矩阵行数变多,你还得一个个加matrix[N],太麻烦了。下面给你两个更通用、更高效的方案,完美适配任意维度的同规格矩阵求和:
方案一:嵌套arrayMap + arrayZip(最直观的通用写法)
这个方法通过两次打包数组,自动对齐所有矩阵的对应元素后求和,完全不需要手动指定维度:
SELECT arrayMap( -- 遍历每一行的打包结果,对该行的所有列元素求和 row -> arrayMap(elem -> sum(elem), arrayZip(row)), -- 先把所有矩阵的对应行打包在一起 arrayZip(matrix) ) AS result_matrix FROM ( SELECT 1 AS id, [[1,3], [2,4]] AS matrix UNION ALL SELECT 2 AS id, [[2,4], [3,5]] AS matrix UNION ALL SELECT 3 AS id, [[1,2], [1,0]] AS matrix )
逻辑拆解:
arrayZip(matrix)会把所有输入矩阵的第一行合并成一个数组,第二行合并成另一个数组,比如示例中会得到:[[[1,3],[2,4],[1,2]], [[2,4],[3,5],[1,0]]]- 外层
arrayMap遍历每一行的打包结果,内层arrayZip再把该行里的对应列元素打包(比如第一行变成[[1,2,1], [3,4,2]]) - 最后对每个打包后的列元素执行
sum,就得到逐元素求和的结果矩阵。
方案二:利用arrayReduce简化写法
如果你的ClickHouse版本支持对嵌套数组的sum聚合,还可以用更简洁的arrayReduce写法:
SELECT arrayMap( row -> arrayReduce('sum', row), arrayZip(matrix) ) AS result_matrix FROM ( SELECT 1 AS id, [[1,3], [2,4]] AS matrix UNION ALL SELECT 2 AS id, [[2,4], [3,5]] AS matrix UNION ALL SELECT 3 AS id, [[1,2], [1,0]] AS matrix )
这里用arrayReduce('sum', row)替代了内层的arrayMap + sum,逻辑和方案一完全一致,但代码更紧凑。
为什么这些方案更优?
- 通用性强:不管你的矩阵是2x2、3x3还是NxM,只要所有输入矩阵的维度完全一致,查询不需要做任何修改。
- 性能更高:依托ClickHouse原生数组函数的优化实现,比手动逐个指定
sumForEach(matrix[N])的效率高得多,数据量越大优势越明显。
执行上面的查询,你就能得到期望的结果:
┌─result_matrix─┐ │ [[4,9],[6,9]] │ └───────────────┘
内容的提问来源于stack exchange,提问作者olegen
相关产品推荐
相关产品推荐

