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

如何查询SQL Server系统版本表指定列的变更历史?

SQL Server系统版本表提取指定列的有效区间(忽略非目标列变更)

问题描述

我有一个包含约20列的SQL Server系统版本表,所有列的值都会随时间发生变化。希望获取仅部分列(如Name、Company)的变更值及其对应的有效期列(SysStartTime、SysEndTime),忽略其他列(如Location)的变更,但保留因这些变更生成的SysStartTime/SysEndTime值。后续可能还需要扩展到更多列,忽略其他非目标列的变更。

示例数据

NameCompanyLocationSysStartTimeSysEndTime
Employee1Company ANew York2023-11-23 05:28:46.95712142023-12-07 05:20:40.7315348
Employee1Company ASan Francisco2023-12-07 05:20:40.73153482024-01-26 05:13:37.1539216
Employee1Company BBerlin2024-01-26 05:13:37.15392162024-01-27 05:13:28.0830253
Employee1Company ATokyo2024-01-27 05:13:28.08302532024-03-09 05:12:29.7629149
Employee1Company ARome2024-03-09 05:12:29.76291492024-04-13 04:10:13.4617646
Employee1Company AKinshasa2024-04-13 04:10:13.46176469999-12-31 23:59:59.9999999
Employee2Company ANewtown2023-11-23 05:28:46.95712142024-01-26 05:13:37.1539216
Employee2Company AOldtown2024-01-26 05:13:37.15392162024-04-13 04:10:13.4617646
Employee2Company CDowntown2024-04-13 04:10:13.46176469999-12-31 23:59:59.9999999

期望输出

NameCompanySysStartTimeSysEndTime
Employee1Company A2023-11-23 05:28:46.95712142024-01-26 05:13:37.1539216
Employee1Company B2024-01-26 05:13:37.15392162024-01-27 05:13:28.0830253
Employee1Company A2024-01-27 05:13:28.08302539999-12-31 23:59:59.9999999
Employee2Company A2023-11-23 05:28:46.95712142024-04-13 04:10:13.4617646
Employee2Company C2024-04-13 04:10:13.46176469999-12-31 23:59:59.9999999

解决方案

核心思路是将连续的、目标列值相同的行归为一组,每组取最早的SysStartTime和最晚的SysEndTime,以此忽略非目标列的变更并保留正确时间区间。使用窗口函数实现分组标记,再聚合得到结果:

WITH RankedRows AS (
    SELECT 
        Name,
        Company,
        SysStartTime,
        SysEndTime,
        -- 标记当前行与上一行目标列是否一致,不一致则生成新组
        SUM(CASE WHEN 
            LAG(Name) OVER (PARTITION BY Name ORDER BY SysStartTime) = Name 
            AND LAG(Company) OVER (PARTITION BY Name ORDER BY SysStartTime) = Company 
            THEN 0 ELSE 1 END) 
        OVER (PARTITION BY Name ORDER BY SysStartTime) AS GroupId
    FROM YourTableName -- 替换为你的实际表名
)
SELECT 
    Name,
    Company,
    MIN(SysStartTime) AS SysStartTime,
    MAX(SysEndTime) AS SysEndTime
FROM RankedRows
GROUP BY Name, Company, GroupId
ORDER BY Name, SysStartTime;

关键说明

  1. PARTITION BY Name:按员工姓名单独分组处理,避免不同员工的记录相互干扰
  2. LAG()函数:获取当前行的上一行记录,对比目标列(Name、Company)是否一致
  3. SUM() OVER():生成分组ID,每当目标列发生变化时分组ID递增,将连续相同的目标列记录归为同一组
  4. GROUP BY聚合:按分组ID合并记录,取每组的最小起始时间和最大结束时间,得到合并后的有效区间

扩展目标列的方法

如果后续需要新增目标列(如Department),只需在CASE WHEN条件中添加对应列的对比即可:

SUM(CASE WHEN 
    LAG(Name) OVER (PARTITION BY Name ORDER BY SysStartTime) = Name 
    AND LAG(Company) OVER (PARTITION BY Name ORDER BY SysStartTime) = Company
    AND LAG(Department) OVER (PARTITION BY Name ORDER BY SysStartTime) = Department -- 新增列对比
    THEN 0 ELSE 1 END) 
OVER (PARTITION BY Name ORDER BY SysStartTime) AS GroupId

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 03:22:33