【问题标题】:INSERT INTO based on SELECT and versioned record基于 SELECT 和版本化记录的 INSERT INTO
【发布时间】:2020-06-03 16:20:01
【问题描述】:

我有一个包含员工当前状态的表格,如下所示:

 SELECT EmployeeId ,OfficeId from EmpCurrent

输出如下:

EmployeeId OfficeId
54          67
64          57
89          23

我还有另一个表,其中包含员工的完整历史记录,但未记录的 OfficeId 除外(我添加了从 EmpCurrent 插入的 NULL 列 OfficeId):

SELECT EmployeeId ,Func AS [Function],OfficeId,Version from EmpHistory

EmployeeId=54 的输出如下所示:

EmployeeId Function OfficeId Version
54         Manager  NULL     1
54         Director NULL     2
54         HeadOf   NULL     3

我想从 EmpCurrent 获取 OfficeId 并将其插入到每个 Employee 的最后一个版本(最大版本)的 EmpHistory 中,我的输出将如下所示:

EmployeeId Function OfficeId Version
54         Manager  NULL     1
54         Director NULL     2
54         HeadOf   67       3

【问题讨论】:

  • 到目前为止您尝试了哪些方法,您在哪里遇到了困难?对于correlated subquery 或窗口函数,这是一个非常标准的用例。

标签: sql sql-server tsql


【解决方案1】:

demo on db<>fiddle

首先,你需要得到3个字段h.EmployeeId, c.OfficeId, max(Version) as MaxVersion

其次,#EmpHistory 表上更新h.OfficeId = cte.OfficeId 2 个条件h.EmployeeId = cte.EmployeeId and MaxVersion = h.Version

完整代码

;with cte as( 
select h.EmployeeId, c.OfficeId, max(Version) as MaxVersion
from #EmpHistory h
inner join #EmpCurrent c on h.EmployeeId = c.EmployeeId
group by h.EmployeeId, c.OfficeId
)

update h
set h.OfficeId = cte.OfficeId
from #EmpHistory h
inner join cte on h.EmployeeId = cte.EmployeeId and MaxVersion = h.Version

输出

【讨论】:

    【解决方案2】:

    如果您想要join 的最新值,则:

    select eh.*, ec.officeid
    from (select eh.*,
                 row_number() over (partition by employeeid order by version desc) as seqnum
          from emphistory eh
         ) eh left join
         empcurrent ec
         on ec.employeeid = eh.employeeid and eh.seqnum = 1;
    

    这是您对left join 中的first 表进行过滤的不寻常情况之一。你也可以这样做:

    select eh.*,
           (case when eh.seqnum = 1 then ec.officeid end) as officeid
    from (select eh.*,
                 row_number() over (partition by employeeid order by version desc) as seqnum
          from emphistory eh
         ) eh left join
         empcurrent ec
         on ec.employeeid = eh.employeeid ;
    

    【讨论】:

      【解决方案3】:
      ;WITH CTE_EMP
      AS
      (
          SELECT 
              EH.EmployeeId
              ,Version        = MAX(Version)
          FROM
              EmpHistory AS EH
          GROUP BY
              EH.EmployeeId
      )
      select 
           EH.EmployeeId
          ,EH.Func
          ,OfficeId       = CASE WHEN CTE.Version = EH.Version THEN EC.OfficeId END
          ,EH.Version
      from 
          EmpHistory AS EH 
          LEFT OUTER JOIN EmpCurrent AS EC ON EC.EmployeeId = EH.EmployeeId
          LEFT OUTER JOIN CTE_EMP AS CTE ON CTE.EmployeeId = EH.EmployeeId
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-01-23
        • 1970-01-01
        • 2013-10-01
        • 1970-01-01
        • 2023-02-09
        • 1970-01-01
        • 2014-03-22
        相关资源
        最近更新 更多