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

MySQL查询中为姓名年度首次出现标记1,其余标记0

如何在SQL中标记姓名每年的首次出现?

我明白你的需求——想要给每个姓名在对应年份里的第一条记录标记1,其余标记0,而且之前拆分查询关联的方式还导致了重复数据,确实挺头疼的。其实这个需求用窗口函数就能完美解决,不用绕弯路。

先回顾下你的原始表tbl_name:

IDNameMonthQuarterYear
1AJan12019
1AFeb12019
2BMay22019
3CMay22018

你的目标是生成带Unique Count列的结果集,接下来看具体实现:

核心解决方案:用ROW_NUMBER()窗口函数

窗口函数可以在不拆分表的前提下,对分组后的记录进行排序和标记,完全避免重复数据的问题。

支持标准窗口函数的数据库(MySQL 8.0+/PostgreSQL/SQL Server/Oracle)

这些数据库直接用下面的SQL语句即可:

SELECT 
    ID,
    Name,
    Month,
    Quarter,
    Year,
    CASE 
        WHEN ROW_NUMBER() OVER (PARTITION BY Name, Year ORDER BY Month) = 1 THEN 1 
        ELSE 0 
    END AS `Unique Count`
FROM tbl_name;
  • PARTITION BY Name, Year:把数据按「姓名+年份」分组,确保我们只在同一个人同一年的记录里判断首次出现。
  • ORDER BY Month:给每组内的记录按月份排序,这样第一个月份的记录就是该姓名当年的首次出现,标记为1。如果你的月份是字符串(比如Jan、Feb),大部分数据库会按字典序正常排序,和实际月份顺序一致;如果是数字格式的月份,排序更准确。

如果你更信任ID的自增顺序来判断首次出现,也可以把排序字段换成ID:

SELECT 
    ID,
    Name,
    Month,
    Quarter,
    Year,
    CASE 
        WHEN ROW_NUMBER() OVER (PARTITION BY Name, Year ORDER BY ID) = 1 THEN 1 
        ELSE 0 
    END AS `Unique Count`
FROM tbl_name;

旧版本MySQL(5.x及以下,不支持窗口函数)

如果你的MySQL版本比较老,不支持窗口函数,可以用子查询来实现:

SELECT 
    t1.ID,
    t1.Name,
    t1.Month,
    t1.Quarter,
    t1.Year,
    CASE 
        WHEN t1.ID = (SELECT MIN(t2.ID) FROM tbl_name t2 WHERE t2.Name = t1.Name AND t2.Year = t1.Year) THEN 1 
        ELSE 0 
    END AS `Unique Count`
FROM tbl_name t1;

这个逻辑是通过子查询找到每个「姓名+年份」组合下的最小ID(也就是最早插入的记录),匹配上的标记为1,其他为0。

为什么之前的关联方式会出问题?

你之前拆分查询关联导致重复,大概率是因为去重后的表和原表关联时,一条去重记录对应多条原表记录,数据库会把这些记录全部返回,自然就产生了重复。而窗口函数是在原表的每条记录上直接计算标记,不会引入额外的重复数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:12:15