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

如何正确编写PostgreSQL统计公司用户占比的查询语句?

错误原因说明

你提交的SQL存在3个核心问题,触发语法报错:

  1. 括号没有闭合:计算百分比的子查询只写了左括号(,没有对应的右括号闭合,PostgreSQL解析到语句末尾未找到合法终止标识,就会报终止符相关的语法错误,哪怕你没有写;也会触发该类报错
  2. 同层级别名引用非法:在同一条SELECT语句中,不能直接引用刚定义的字段别名nbre_utilisateurs计算其他字段,SQL执行顺序中SELECT字段解析晚于聚合逻辑,别名无法在同层级复用
  3. 子查询逻辑错误:子查询内不存在nbre_utilisateurs这个别名,且不需要额外关联companies表、分组就能计算总用户数,逻辑完全冗余错误
实现方案

方案一:窗口函数实现(性能最优)

PostgreSQL原生支持窗口函数,该方案只需要扫描一次关联后的表就能出结果,是执行效率最高的写法:

SELECT 
    c.name AS societe,
    COUNT(u.id) AS nbre_utilisateurs,
    ROUND(COUNT(u.id) * 100.0 / SUM(COUNT(u.id)) OVER (), 2) AS pourcentage
FROM companies c
LEFT JOIN users u ON c.id = u.company_id
GROUP BY c.id, c.name
ORDER BY nbre_utilisateurs DESC;

说明:

  • 使用LEFT JOIN会保留没有用户的公司,对应计数为0,如果你不需要保留无用户的公司,换成INNER JOIN即可
  • 乘100.0是为了触发浮点运算避免整数截断,ROUND第二个参数控制保留的小数位数,可按需调整
  • 窗口函数SUM(COUNT(u.id)) OVER ()会直接在聚合后的结果集上计算全局用户总数,不需要额外子查询

方案二:CTE预计算总用户数(兼容性更好)

该写法兼容更多低版本数据库,逻辑更易懂,适合新手理解:

-- 预计算全局总用户数
WITH total_user_count AS (
    SELECT COUNT(*) AS total FROM users
)
SELECT 
    c.name AS societe,
    COUNT(u.id) AS nbre_utilisateurs,
    ROUND(COUNT(u.id) * 100.0 / tc.total, 2) AS pourcentage
FROM companies c
LEFT JOIN users u ON c.id = u.company_id
CROSS JOIN total_user_count tc
GROUP BY c.id, c.name, tc.total
ORDER BY nbre_utilisateurs DESC;
性能对比

窗口函数的方案执行速度更快:

  • 窗口函数仅需要对两张表做一次关联、一次聚合、一次窗口计算就能出结果
  • CTE方案需要多扫描一次users表计算总用户数,表数据量越大,两种方案的性能差距越明显
  • 如果给users表的company_id字段加索引,两种方案的执行速度都会有大幅提升

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 13:09:01