You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何对分组后某列的所有值执行按位或运算

解决PostgreSQL中按用户聚合group_id的按位或运算问题

这问题我之前处理过,PostgreSQL本身没有内置的按位或聚合函数,不过咱们有两种简单的办法可以实现你要的效果:

方法一:自定义按位或聚合函数(推荐,复用性强)

直接创建一个自定义的聚合函数,以后想用的时候直接调用就行,非常方便:

CREATE AGGREGATE bit_or_agg(integer) (
    SFUNC = bit_or,
    STYPE = integer,
    INITCOND = 0
);

这个函数的逻辑很简单:

  • SFUNC = bit_or:指定用PostgreSQL内置的bit_or函数作为每一步的计算逻辑
  • STYPE = integer:聚合过程中状态值的类型是整数
  • INITCOND = 0:初始值设为0,因为0和任何数按位或都等于那个数本身,不会影响结果

创建完之后,直接用这个聚合函数查询就搞定了:

SELECT user_id, bit_or_agg(group_id) AS groups
FROM user_group
GROUP BY user_id;

运行这个查询就能得到你期望的结果:

user_id | groups

1 | 7
2 | 9

方法二:递归CTE(无需创建对象,适合临时场景)

如果没有权限创建自定义函数,或者只是临时用一次,用递归CTE处理数组也能实现:

WITH user_groups AS (
    -- 先获取每个用户对应的group_id数组
    SELECT user_id, array_agg(group_id) AS group_array
    FROM user_group
    GROUP BY user_id
),
recursive_or AS (
    -- 递归初始步骤:取每个数组的第一个元素作为初始值
    SELECT 
        user_id,
        group_array,
        group_array[1] AS current_or,
        1 AS idx
    FROM user_groups
    WHERE array_length(group_array, 1) >= 1
    UNION ALL
    -- 递归迭代:依次将当前结果和下一个元素做按位或
    SELECT
        ro.user_id,
        ro.group_array,
        ro.current_or | ro.group_array[ro.idx + 1],
        ro.idx + 1
    FROM recursive_or ro
    WHERE ro.idx < array_length(ro.group_array, 1)
)
-- 取每个用户最后一次递归的结果(也就是处理完所有元素后的按位或值)
SELECT user_id, current_or AS groups
FROM recursive_or
WHERE idx = array_length(group_array, 1);

这个方法的思路是把数组拆成逐个元素,一步步累积计算按位或,最后得到最终结果。

两种方法都能达到你的需求,优先推荐第一种,毕竟自定义聚合函数之后再用就太方便了~

内容的提问来源于stack exchange,提问作者afzalex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:04:20