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

如何获取emp表中health字段首次记录后发生变更的emp_id?

现有SQL问题分析

你当前写的查询语句存在两个核心逻辑错误,无法满足需求:

  • count(e.health) 统计时会自动忽略health为null的行,若员工健康状态从非空变更为null,该计数不会增长,会漏判符合条件的员工
  • 现有逻辑仅统计非空健康记录数大于1的员工,没有和首条记录做对比,若员工多次录入相同的健康值(比如多次记录都是heart),会被误判为发生了变更
正确查询方案

核心逻辑为:先提取每个员工最早的健康状态作为基准,再判断该员工是否存在任意一条晚于首条的记录和基准值不同。

方案1:窗口函数实现(兼容性较好,大部分SQL引擎支持)

SELECT DISTINCT emp_id
FROM (
    SELECT 
        emp_id,
        health,
        -- 取每个员工最早的health值作为对比基准
        FIRST_VALUE(health) OVER (PARTITION BY emp_id ORDER BY modification_date ASC) AS first_health,
        -- 取每个员工的记录排序编号,用于排除只有1条记录的员工
        ROW_NUMBER() OVER (PARTITION BY emp_id ORDER BY modification_date ASC) AS rn
    FROM emp
) t
WHERE rn > 1 -- 排除仅1条记录、没有变更可能的员工
  AND (
      health <> first_health 
      OR (health IS NULL AND first_health IS NOT NULL)
      OR (health IS NOT NULL AND first_health IS NULL)
  )

如果你使用的SQL引擎支持IS NOT DISTINCT FROM语法,可以简化条件判断:

WHERE rn > 1 AND health IS NOT DISTINCT FROM first_health = FALSE

方案2:子查询关联实现(适合不支持窗口函数的低版本SQL引擎)

SELECT DISTINCT e.emp_id
FROM emp e
INNER JOIN (
    -- 先查询每个员工首条记录的健康状态
    SELECT 
        e1.emp_id,
        e1.health AS first_health,
        MIN(e1.modification_date) AS first_modify_date
    FROM emp e1
    GROUP BY e1.emp_id, e1.health
) t ON e.emp_id = t.emp_id
WHERE e.modification_date > t.first_modify_date
  AND (
      e.health <> t.first_health
      OR (e.health IS NULL AND t.first_health IS NOT NULL)
      OR (e.health IS NOT NULL AND t.first_health IS NULL)
  )

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 11:36:03