基于日期去除SQL重复数据求助:每日仅保留单条用户登录记录
解决每个客户每日仅保留一条登录记录的SQL错误问题
错误原因分析
你碰到的报错源于SQL的GROUP BY语义规则:SELECT子句中的字段要么必须出现在GROUP BY列表里,要么必须用聚合函数(如MIN/MAX)包裹。你用了SELECT *,但仅按日期分组,loginId、customerName等字段既没被分组,也没有聚合处理,因此触发错误。另外你的逻辑存在偏差——需求是每个客户每日一条记录,只按日期分组会把所有客户同一天的记录强行合并,完全不符合需求。
正确解法
方法1:用窗口函数(推荐,灵活选择保留哪条记录)
通过ROW_NUMBER()按「客户+日期」分区,给每个客户每日的登录记录排序,再筛选出第一条(可选择保留当日最早或最晚的登录记录):
WITH ranked_logins AS ( SELECT t1.loginId, t1.loginTimeStamp, t1.customerName, t2.* -- 按需选择table2的字段,避免直接用*造成冗余 FROM table1 t1 JOIN table2 t2 ON t1.a = t2.a ROW_NUMBER() OVER ( PARTITION BY t1.customerName, CAST(t1.loginTimeStamp AS DATE) ORDER BY t1.loginTimeStamp ASC -- ASC选当日最早登录,DESC选最晚 ) AS rn ) SELECT * FROM ranked_logins WHERE rn = 1;
方法2:用GROUP BY+聚合函数(适合字段有明确聚合规则的场景)
如果只需保留每个客户每日的某一条记录(比如当日最早的loginId),可以按「客户+日期」分组,对其他字段使用聚合函数:
SELECT MIN(t1.loginId) AS loginId, -- 选当日最早的loginId,MAX则是最晚 CAST(t1.loginTimeStamp AS DATE) AS loginDate, t1.customerName, MIN(t2.some_field) AS some_field -- 对table2的字段用聚合,按需选MIN/MAX FROM table1 t1 JOIN table2 t2 ON t1.a = t2.a GROUP BY t1.customerName, CAST(t1.loginTimeStamp AS DATE);
注意事项
- 避免直接用
SELECT *,明确指定需要的字段,减少不必要的错误和数据冗余。 - 必须按
customerName + 日期分组,才能实现「每个客户每日一条」的需求,仅按日期分组逻辑完全错误。
内容的提问来源于stack exchange,提问作者Scylla
相关产品推荐
相关产品推荐

