如何按城市分组对User_created_date列排名并查询各城市首个用户创建时间
解决方案
先明确核心需求的两种常见实现场景,同时修正你之前的逻辑问题:
1. 获取每个城市的首个用户创建时间,并按该时间对城市排名
你之前先排序再分组的方式无法保留排名所需的上下文,正确做法是先通过分组得到每个城市的最早用户时间,再用窗口函数对结果排名:
-- 先计算每个城市的首个用户创建时间 WITH city_first_timestamps AS ( SELECT "Customer city", MIN("User_created_date") AS first_user_time FROM your_table GROUP BY "Customer city" ) -- 基于首个时间对城市排名 SELECT "Customer city", first_user_time, -- 按首个时间升序排名,最早的城市排第1 RANK() OVER (ORDER BY first_user_time ASC) AS city_rank FROM city_first_timestamps ORDER BY city_rank;
2. 每个城市内部按用户创建时间排名,同时显示该城市的首个用户时间
如果需求是给每个用户标记其在所属城市的创建时间排名,同时展示该城市的最早用户时间,直接用窗口函数即可,无需提前分组:
SELECT ID, "Customer city", "User_created_date", -- 计算当前城市的首个用户时间 MIN("User_created_date") OVER (PARTITION BY "Customer city") AS city_first_user_time, -- 按城市分组,组内按创建时间升序排名 RANK() OVER (PARTITION BY "Customer city" ORDER BY "User_created_date" ASC) AS user_rank_in_city FROM your_table ORDER BY "Customer city", user_rank_in_city;
关于你之前的问题
先排序再分组的逻辑不适用:分组操作会聚合掉排序后的行级数据,无法为后续排名提供分组上下文。而窗口函数(OVER (PARTITION BY ...))可以在保留所有行数据的同时,按指定维度(比如城市)进行分组计算,这才是实现这类排名需求的正确方式。
另外注意:你的User_created_date带时区偏移,若需要统一时区计算(比如转UTC),可以用对应数据库的时区转换函数,例如PostgreSQL的AT TIME ZONE 'UTC'、MySQL的CONVERT_TZ(),确保时间比较的准确性。
内容的提问来源于stack exchange,提问作者Data Guy
相关产品推荐
相关产品推荐

