2014-08-28 270 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