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

如何保留同一email对应最小created_timestamp的行并删除其他行?

解决同一邮箱仅保留最早创建时间行的问题

我懂你遇到的困扰——想给每个邮箱只留创建时间最早的那一行,用GROUP BY的时候发现完全不符合需求,确实踩了个常见的SQL坑。下面给你两种实用的解决方案,适配不同的数据库场景:

示例数据

UUID email      created_timestamp
1    a@g.com    2017-05-01
2    a@g.com    2018-05-01
3    a@g.com    2018-05-20
4    b@g.com    2017-04-01
5    b@g.com    2017-06-01

方法一:窗口函数(推荐,直观灵活)

窗口函数是处理这种分组排序需求的绝佳工具,大多数现代数据库(PostgreSQL、MySQL 8.0+、SQL Server等)都支持:

WITH ranked_records AS (
    SELECT
        UUID,
        email,
        created_timestamp,
        -- 按邮箱分组,按创建时间升序编号,最早的行编号为1
        ROW_NUMBER() OVER (PARTITION BY email ORDER BY created_timestamp ASC) AS row_rank
    FROM your_table
)
SELECT UUID, email, created_timestamp
FROM ranked_records
WHERE row_rank = 1;

说明:

  • PARTITION BY email:把数据按邮箱分成独立的组
  • ORDER BY created_timestamp ASC:每个组内按创建时间从小到大排序,确保最早的行排在最前
  • ROW_NUMBER():给每个组内的行分配唯一编号,最早的行编号为1,最后筛选出编号为1的行即可

如果你的场景中,同一邮箱可能有多行相同的最早创建时间,且需要保留所有这些行,可以把ROW_NUMBER()换成RANK()或者DENSE_RANK(),这样相同时间的行都会得到编号1。

方法二:子查询关联(兼容旧版本数据库)

如果你的数据库不支持CTE或窗口函数(比如MySQL 5.7及更早版本),可以用子查询先找出每个邮箱的最小创建时间,再和原表关联匹配:

SELECT t1.UUID, t1.email, t1.created_timestamp
FROM your_table t1
INNER JOIN (
    -- 先找出每个邮箱对应的最早创建时间
    SELECT email, MIN(created_timestamp) AS earliest_time
    FROM your_table
    GROUP BY email
) t2 
ON t1.email = t2.email AND t1.created_timestamp = t2.earliest_time;

说明:

  • 子查询t2负责提取每个邮箱的最小创建时间
  • 通过INNER JOIN把原表t1和子查询结果关联,匹配邮箱和对应的最早时间,从而得到目标行
  • 这种方法会保留同一邮箱所有拥有最早创建时间的行(如果存在多行时间相同的情况)

为什么之前的GROUP BY不行?

你之前尝试的GROUP BY如果按UUID分组,相当于每行单独成组,完全达不到聚合邮箱的目的;如果强行按email分组,你没办法直接拿到对应的UUID——因为UUID是唯一值,用MIN(UUID)之类的聚合函数得到的结果,不一定对应最早创建时间的那行,所以这种思路走不通。

预期输出

UUID email      created_timestamp
1    a@g.com    2017-05-01
4    b@g.com    2017-04-01

内容的提问来源于stack exchange,提问作者Flavio de Falcao e Helena

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:28:09