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

PostgreSQL使用DISTINCT ON计数时报错:at or near "on"

排查PostgreSQL中DISTINCT ON与COUNT结合的语法错误

嘿,我来帮你梳理下这个问题~你遇到的at or near "on"语法错误,根源是DISTINCT ON是PostgreSQL特有的行级去重语法,它不能直接嵌套在COUNT()函数的括号里当参数用,再加上原语句还有括号不匹配的问题,自然就报错了。

下面我根据两种常见的需求场景,给出对应的正确写法:

场景1:统计指定时间段内有打卡记录的不同用户数量

如果你的需求只是想知道这段时间里有多少个不同的用户完成了打卡,那完全不需要用到DISTINCT ON,直接用COUNT(DISTINCT a.userid)就能实现:

SELECT COUNT(DISTINCT a.userid) AS unique_user_count
FROM checkinout a
LEFT JOIN userinfo b ON b.userid = a.userid
WHERE a.checktime >= '2017-12-28 06:15:00' 
  AND a.checktime <= '2017-12-28 07:45:00';

场景2:按userid去重(保留每个用户的单条打卡记录)后统计总数

如果你的需求是对每个userid只保留一条打卡记录(比如最早或最晚的那次),再统计这些去重后的记录总数,这时候就需要把DISTINCT ON放在内层查询中,外层再做COUNT:

比如保留每个用户最早的打卡记录:

SELECT COUNT(*) AS deduplicated_record_count
FROM (
  SELECT DISTINCT ON (a.userid) 
         a.userid, b.name, a.checktime
  FROM checkinout a
  LEFT JOIN userinfo b ON b.userid = a.userid
  WHERE a.checktime >= '2017-12-28 06:15:00' 
    AND a.checktime <= '2017-12-28 07:45:00'
  ORDER BY a.userid, a.checktime ASC -- 按userid分组,取最早的打卡记录
) AS deduplicated_records;

要是想保留每个用户最晚的打卡记录,只需要把ORDER BY里的a.checktime ASC改成a.checktime DESC就行。

小提醒

使用DISTINCT ON时必须配合ORDER BY,而且ORDER BY的第一个字段必须是DISTINCT ON指定的分组字段(这里是a.userid),这样PostgreSQL才能明确每个分组要保留哪一条记录。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:20:09