1

我在 SQL Server 2008 R2 中链接了 MAS(会计系统)的数据库。工资单记录在该数据库中的工作方式是,每个季度都会制作工资单表存档,并制作一个新的当前季度表,并删除所有已离职的员工。它确实有唯一的员工 ID。存档和当前版本的结构相同。

因此,在今年第二季度,在第一季度被解雇的员工仅在数据库的第一季度副本中。在第一季度和第二季度工作的员工在第一季度副本和第二季度副本中。在第二季度雇用的员工仅在第二季度出现。

我需要能够构建一个集合(临时表、视图等)来使用,其中包括每个员工的最新记录。该集合将作为营业额、职位平均工资等查询的基础。

UNION我可以使用一个列足够快地构建一个 ID 列表EmployeeID,但是其他列会随着时间而变化(工资率、地址等),所以我不能简单地UNION列出所有列,因为我会有一些员工的重复项。

是否有一种合理有效的方法将历史数据库合并在一起,只保留每个员工的最新行?以这种方式表达了这个问题,我是否应该只制作一系列MERGEs,从最新到最旧的存档副本中退一步,在不匹配时插入?有没有更好的办法?

4

1 回答 1

0

有几种方法可以解决这个问题。这是一个:

  • 创建一个视图以合并表,为每个表添加适当的存档日期列
  • 针对 EmployeeID 上的 Group 视图创建子查询并获取 MAX 存档日期
  • 使用子查询加入视图,获取每个员工的最新记录

创建示例表架构和测试数据

    SET NOCOUNT ON

    IF OBJECT_ID('Employee', 'U') IS NOT NULL DROP TABLE Employee;
    GO
    IF OBJECT_ID('Employee2012Q1', 'U') IS NOT NULL DROP TABLE Employee2012Q1;
    GO
    IF OBJECT_ID('Employee2012Q2', 'U') IS NOT NULL DROP TABLE Employee2012Q2;
    GO

    CREATE TABLE dbo.Employee (
        EmployeeID      int IDENTITY(1,1)   NOT NULL    PRIMARY KEY
       ,EmployeeName    varchar(50)         NOT NULL
       ,StartDate       smalldatetime       NOT NULL
       ,EndDate         smalldatetime       NULL
       ,Salary          decimal(18,2)       NOT NULL
       ,Position        varchar(50)         NOT NULL
       ,HomeAddress     varchar(200)        NOT NULL
    )

    -- Employees hired
    INSERT dbo.Employee SELECT 'John Doe', '01/01/2012', NULL, 50000, 'Developer', '12345 Main St, New York, NY'
    INSERT dbo.Employee SELECT 'Jane Doe', '01/01/2012', NULL, 52000, 'Developer', '837 1st St, New York, NY'

    -- Employee fired
    UPDATE A
       SET A.EndDate = '02/01/2012'
      FROM dbo.Employee A
     WHERE A.EmployeeName = 'John Doe'

    -- Table archived
    SELECT * INTO dbo.Employee2012Q1 FROM dbo.Employee

    --  Remove fired employees
    DELETE dbo.Employee WHERE EndDate IS NOT NULL

    -- Employee hired
    INSERT dbo.Employee SELECT 'Jack Flash', '04/01/2012', NULL, 73000, 'Manager', '9580 21st St, New York, NY'

    -- Employee fired
    UPDATE A
       SET A.EndDate = '05/01/2012'
      FROM dbo.Employee A
     WHERE A.EmployeeName = 'Jack Flash'

    -- Table archived
    SELECT * INTO dbo.Employee2012Q2 FROM dbo.Employee

    --  Remove fired employees
    DELETE dbo.Employee WHERE EndDate IS NOT NULL

    SET NOCOUNT OFF
    GO

创建一个合并所有员工表的视图

    IF OBJECT_ID('EmployeeArchive', 'V') IS NOT NULL DROP VIEW dbo.EmployeeArchive
    GO
    CREATE VIEW dbo.EmployeeArchive
    AS
    SELECT CONVERT(smalldatetime, CONVERT(char(10), GETDATE(), 101)) as [ArchiveDate]
          ,EmployeeID
          ,EmployeeName
          ,StartDate
          ,EndDate
          ,Salary
          ,Position
          ,HomeAddress
     FROM dbo.Employee 
    UNION ALL
    SELECT CONVERT(smalldatetime, '03/31/2012') as [ArchiveDate]
          ,EmployeeID
          ,EmployeeName
          ,StartDate
          ,EndDate
          ,Salary
          ,Position
          ,HomeAddress
      FROM dbo.Employee2012Q1 
    UNION ALL
    SELECT CONVERT(smalldatetime, '06/30/2012') as [ArchiveDate]
          ,EmployeeID
          ,EmployeeName
          ,StartDate
          ,EndDate
          ,Salary
          ,Position
          ,HomeAddress
      FROM dbo.Employee2012Q2 
    GO

获取每位员工的最新信息

    SELECT A.*
      FROM dbo.EmployeeArchive A
      JOIN (
            SELECT EmployeeID, MAX(ArchiveDate) as MaxArchiveDate
              FROM dbo.EmployeeArchive
             GROUP BY EmployeeID
           ) B
        ON A.EmployeeID  = B.EmployeeID
       AND A.ArchiveDate = B.MaxArchiveDate
于 2013-04-12T05:48:37.250 回答