SQL Server:存储最近5个日期

时间:2017-10-10 11:46:29

标签: sql-server pseudocode

寻找关于如何编写此代码的建议。

我有一个从一个系统移植到另一个系统的唯一值表。而且我想记录一下记录结束时的最后5个日期。

例如,项目A在2017年10月1日从System X刷新到System Y,我想将此日期存储在表格中。然后在接下来的一个月里,它又被带了4次,所以我希望这些日期值也写入该表。

既然已经编写了最后5个日期,我需要一些维护代码的方法,以便任何新的日期都会覆盖表数据,这样我们最多只能拥有最近5个更新日期。表

示例数据; 日期列表示每个属性行发生的最后5次更新。

Property ID's, Date 1,   Date 2,   Date 3,  Date 4,   Date 5
1              01/07/17, 01/08/17 01/10/17 05/10/17 10/10/17
2              01/01/17 01/03/17 01/06/17 05/10/17 10/10/17
3              01/02/17 05/02/17 01/10/17 05/10/17 10/10/17
4              01/03/17 01/08/17 01/10/17

如果属性4具有来自系统X的更新,则填充日期4。 如果属性3有来自系统x的更新,则日期2到5将向左移动一个位置,日期5将填充最新日期。

这是记录最近5次更新的最佳方式。

或者,我可以将每个属性id和更新日期写入表中,并进行某种清理程序,每个属性只保留5个条目。

如果我含糊不清,请道歉。

2 个答案:

答案 0 :(得分:0)

如果您想保留最近的5条记录,那么它似乎是MERGE,允许同时进行INSERTDELETE活动。

此脚本演示MERGE,每ID个值保留最近5行:

create table #History (ID int not null, OccurredAt datetime2(7) not null)
go
declare @current table (ID int not null)
insert into @current (ID) values (1),(3)

;With Keeps as (
    select
        *,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY OccurredAt desc) as rn
    from #History
    where ID in (select ID from @current)
)
merge into #History t
using (select ID,SYSDATETIME() from @current
        union all
      select ID,OccurredAt from Keeps where rn between 1 and 4) s(ID,OccurredAt)
on
    t.ID = s.ID and
    t.OccurredAt = s.OccurredAt
when not matched then insert (ID,OccurredAt) values (s.ID,s.OccurredAt)
when not matched by source and t.ID in (select ID from @current) then delete;

waitfor delay '00:00:01'
go 30
select * from #History

希望您能看到CTE如何找到应保留的“其他”行以及两个not matched子句如何处理INSERTDELETE活动。

答案 1 :(得分:0)

更好地使用表格:

CREATE TABLE dbo.ChangeDates (
    PropertyID int,
    DateChanged date
)

只需在其中写入数据。然后创建视图:

CREATE VIEW dbo.Top5ChangeDates 
AS
WITH cte AS (
    SELECT  PropertyID,
            DateChanged,
            ROW_NUMBER() OVER (PARTITION BY PropertyID ORDER BY DateChanged DESC) as rn
    FROM dbo.ChangeDates
)

SELECT  PropertyID,
        DateChanged
FROM cte
WHERE rn <= 5
GO

或者在插入TRIGGER而不是查看后使用,以清除数据。