如何从最近出现ID的归档表中获取记录

时间:2013-03-26 02:57:59

标签: sql sql-server sql-server-2008-r2 greatest-n-per-group

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

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

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

我可以使用UNION列的EmployeeID快速建立ID列表,但其他列会随着时间的推移而变化(付费率,地址等),所以我不能简单地{{1所有列,因为我将为一些员工提供重复。

是否有合理有效的方法将历史数据库合并在一起,只保留每个员工的最新行?以这种方式提出问题,我是否应该制作一系列UNION s,从最新到最旧的档案副本退回,在不匹配时插入?还有更好的方法吗?

1 个答案:

答案 0 :(得分: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