2014-08-28 269 views
0

我正在尝试通过更改格式来清除不太有用的历史记录表。 对于历史记录表的使用,它与行之间有效的时间有关。将SQL Server点历史记录表迁移到历史记录表

现状:

Unit | Value | HistoryOn  | 
---------------------------------------- 
1  | 123  | 2013-01-05 14:16:00 
1  | 234  | 2013-01-07 12:12:00 
2  | 325  | 2013-01-04 14:12:00 
1  | 657  | 2013-02-04 17:11:00 
3  | 132  | 2013-04-02 13:00:00 

即就出现在这里是因为这个表的增长将日益时,我想知道什么样的地位在一定时间内所有的容器必须耗资源的问题。 (说我想知道在特定日期的所有单位的值)

我的解决办法是在创建一个表格式如下:

Unit | value | HistoryStart   | HistoryEnd   | 
--------------------------------------------------------------------- 
1  | 123  | 2013-01-05 14:16:00 | 2013-01-07 12:11:59 
1  | 234  | 2013-01-07 12:12:00 | 2013-02-04 17:10:59 
1  | 657  | 2013-02-04 17:11:00 | NULL 
2  | 325  | 2013-01-04 14:12:00 | NULL 
3  | 132  | 2013-04-02 13:00:00 | NULL 

注意,在HistoryEnd NULL值在这里表示该行仍是当前状态的代表。

我试过使用HistoryOn字段在表本身上使用左连接。这具有以不希望的方式级联的不幸副作用。

SQL查询中使用:

SELECT * 
FROM webhistory.Units u1 LEFT JOIN webhistory.Units u2 on u1.Unit = u2.Unit 
    AND u1.HistoryOn < u2.HistoryOn 
WHERE u1.Units = 1 

查询的结果如下:

Unit | Value | HistoryOn   | Unit | Value | HistoryOn  | 
------------------------------------------------------------------------------------- 
    1  | 657  | 2013-02-04 17:11:00 | NULL | NULL | NULL 
    1  | 234  | 2013-01-07 12:12:00 | 1  | 657  | 2013-02-04 17:11:00 
    1  | 123  | 2013-01-05 14:16:00 | 1  | 657  | 2013-02-04 17:11:00 
    1  | 123  | 2013-01-05 14:16:00 | 1  | 234  | 2013-01-07 12:12:00 

这种效果是增量,因为每个条目将加入所有的条目比自己更新,而不是只有它后面的第一个条目。

可悲的是,我仍然无法提出一个很好的查询来解决这个问题,并希望能够帮助我解决这一迁移问题的见解或建议。

回答

1

也许我失去了一些东西,但是这似乎工作会发生什么:

CREATE TABLE #webhist(
    Unit int, 
    Value int, 
    HistoryOn datetime 
) 

INSERT INTO #webhist VALUES 
(1, 123, '2013-01-05 14:16:00'), 
(1, 234, '2013-01-07 12:12:00'), 
(2, 325, '2013-01-04 14:12:00'), 
(1, 657, '2013-02-04 17:11:00'), 
(3, 132, '2013-04-02 13:00:00') 

SELECT 
    u1.Unit 
    ,u1.Value 
    ,u1.HistoryOn AS HistoryStart 
    ,u2.HistoryOn AS HistoryEnd 
FROM #webhist u1 
OUTER APPLY (
    SELECT TOP 1 * 
    FROM #webhist u2 
    WHERE u1.Unit = u2.Unit AND u1.HistoryOn < u2.HistoryOn 
    ORDER BY HistoryOn 
) u2 

DROP TABLE #webhist 
+0

谢谢你的回答,虽然我最终没有将它作为我的最终解决方案,但它确实让我明白我的错在哪里。而不是你建议我使用一个嵌套选择,如下所示: 'select *, (从#webhist u2选择top top 1 historyon,其中u2.historyon> u1.historyon和u1.unit = u2.unit) 从#webhist u1;' – MSB 2014-08-29 07:52:18

+0

更简单:)很高兴帮助。 – 2014-08-29 11:07:24

1

第一个数据样本

create table Data(
    Unit int, 
    Value int, 
    HistoryOn datetime) 

insert into Data 
select 1,123,'2013-01-05 14:16:00' 
union select 1  , 234  , '2013-01-07 12:12:00' 
union select 2  , 325  , '2013-01-04 14:12:00' 
union select 1  , 657  , '2013-02-04 17:11:00' 
union select 3  , 132  , '2013-04-02 13:00:00' 

我创建了一个函数来计算HistoryEnd 发现我命名数据表

CREATE FUNCTION dbo.fnHistoryEnd 
(
    @Unit as int, 
    @HistoryOn as datetime 
) 
RETURNS datetime 
AS 
BEGIN 
    -- Declare the return variable here 
    DECLARE @HistoryEnd as datetime 


    select top 1 @HistoryEnd=dateadd(s,-1,d.HistoryOn) 
    from Data d 
    where d.HistoryOn>@HistoryOn and [email protected] 
    order by d.HistoryOn asc 


    RETURN @HistoryEnd 

END 
GO 

然后,查询是微不足道

select *,dbo.fnHistoryEnd(a.Unit,a.HistoryOn) from Data a 
order by Unit, HistoryOn 

EDIT

不要忘记在子查询中按子句排序。如果看不

CREATE TABLE #webhist(
    Unit int, 
    Value int, 
    HistoryOn datetime 
) 

INSERT INTO #webhist VALUES 
(1, 234, '2013-01-07 12:12:00'), 
(2, 325, '2013-01-04 14:12:00'), 
(1, 657, '2013-02-04 17:11:00'), 
(3, 132, '2013-04-02 13:00:00'), 
(1, 123, '2013-01-05 14:16:00') 


select *, (select top 1 historyon from #webhist u2 where u2.historyon > u1.historyon and u1.unit = u2.unit) from #webhist u1; 
select *, (select top 1 historyon from #webhist u2 where u2.historyon > u1.historyon and u1.unit = u2.unit order by u2.HistoryOn) from #webhist u1; 

drop table #webhist 
+0

感谢您的回答,而你的方法工作我最终使用了不同的方法来代替。 – MSB 2014-08-29 07:54:32

+0

@MSB起初我使用你的方法,但我不能让它在sqlfiddle中工作。所以我把sub querry放在一个函数中。不要忘记你的子命令中的u2.HistoryOn命令,就像我在我的功能中所做的一样。看看我的编辑澄清。 – Horaciux 2014-08-29 12:49:43