2009-09-09 79 views
0

我有與(Last record of Join table)中描述的相同的「問題」:我需要加入一個帶有「歷史表」的「主表」,而我只想加入最新(按日期)歷史表的記錄。因此,無論何時我查詢mastertable的記錄,我也會記錄歷史記錄表的「最新」數據。最後一個連接表的記錄(如何優化)

Master Table 
    ID 
    FIRSTNAME 
    LASTNAME 
    ... 

History Table 
    ID 
    LASTACTION 
    DATE 

這是通過連接兩個表和使用子查詢如在上面的鏈接中給出的答案描述的那樣獲取的最新歷史記錄表記錄可能的。

我的問題是: 我該如何解決問題,理論上可能存在兩個歷史記錄與同一日期?

這種加上子選擇真的是性能方面的最佳解決方案嗎?如果我將名爲「ISLATESTRECORD」的歷史表中的其他屬性作爲手動管理的布爾標誌(並且具有唯一的約束),那麼您認爲(我不是所有這些東西的專家)。此屬性將明確標記最新的記錄,我不需要任何子選詞,因爲我可以在連接的where子句中直接使用此屬性。另一方面,這使插入新記錄當然有點複雜:我必須從最新記錄中刪除「ISLATESTRECORD」標誌,我必須插入帶有「ISLATESTRECORD」集的新歷史記錄,並且提交交易。

您認爲推薦的解決方案是什麼?我沒有任何關於子選詞對性能影響的線索:我可能有數百萬個「Mastertable」記錄「,我必須搜索特定的記錄,這些記錄也可以在加入的歷史記錄表的搜索屬性中使用,例如:」給我帶有FIRSTNAME XYZ的Mastertable記錄和歷史記錄表的LASTACTION是「changed_name」。所以這個子選擇可能被稱爲數百萬次。

或者,它是否更好地使用子查找來找到最新的記錄,因爲子查詢是非常有效的,它更好地保持一切正常化?

非常感謝您

+0

什麼數據庫(包括版)? – 2009-09-09 15:39:20

回答

2

我使用自動遞增標識列添加到歷史記錄表中,通過查詢現有表和表上的問題來解決您的問題。通過在歷史記錄表上添加自動遞增標識列,您可以避開日期的獨特問題,並使查詢變得更加簡單。

爲了解決您的表的問題(與SQL Server實例代碼):

DECLARE @MasterTable table (MasterID int,FirstName varchar(20),LastName varchar(20)) 
DECLARE @HistoryTable table (MasterID int,LastAction char(1),HistoryDate datetime) 

INSERT INTO @MasterTable VALUES (1,'AAA','aaa') 
INSERT INTO @MasterTable VALUES (2,'BBB','bbb') 
INSERT INTO @MasterTable VALUES (3,'CCC','ccc') 

INSERT INTO @HistoryTable VALUES (1,'I','1/1/2009') 
INSERT INTO @HistoryTable VALUES (1,'U','2/2/2009') 
INSERT INTO @HistoryTable VALUES (1,'U','3/3/2009') --<<dups 
INSERT INTO @HistoryTable VALUES (1,'U','3/3/2009') --<<dups 
INSERT INTO @HistoryTable VALUES (2,'I','5/5/2009') 
INSERT INTO @HistoryTable VALUES (3,'I','7/7/2009') 
INSERT INTO @HistoryTable VALUES (3,'U','8/8/2009') 

SELECT 
    MasterID,FirstName,LastName,LastAction,HistoryDate 
    FROM (SELECT 
       m.MasterID,m.FirstName,m.LastName,h.LastAction,h.HistoryDate,ROW_NUMBER() OVER(PARTITION BY m.MasterID ORDER BY m.MasterID) AS RankValue 
       FROM @MasterTable m 
        INNER JOIN (SELECT 
            MasterID,MAX(HistoryDate) AS MaxDate 
            FROM @HistoryTable 
            GROUP BY MasterID 
          ) dt ON m.MasterID=dt.MasterID 
        INNER JOIN @HistoryTable h ON dt.MasterID=h.MasterID AND dt.MaxDate=h.HistoryDate 
     ) AllRows 
    WHERE RankValue=1 

OUTPUT:

MasterID FirstName LastName LastAction HistoryDate 
----------- --------- -------- ---------- ----------- 
1   AAA  aaa  U   2009-03-03 
2   BBB  bbb  I   2009-05-05 
3   CCC  ccc  U   2009-08-08 

(3 row(s) affected) 

爲了一個更好的,HistoryTable解決問題(與SQL服務器示例代碼): 這是更好的,因爲它具有自動遞增歷史ID標識列

DECLARE @MasterTable table (MasterID int,FirstName varchar(20),LastName varchar(20)) 
DECLARE @HistoryTableNEW table (HistoryID int identity(1,1), MasterID int,LastAction char(1),HistoryDate datetime) 

INSERT INTO @MasterTable VALUES (1,'AAA','aaa') 
INSERT INTO @MasterTable VALUES (2,'BBB','bbb') 
INSERT INTO @MasterTable VALUES (3,'CCC','ccc') 

INSERT INTO @HistoryTableNEW VALUES (1,'I','1/1/2009') 
INSERT INTO @HistoryTableNEW VALUES (1,'U','2/2/2009') 
INSERT INTO @HistoryTableNEW VALUES (1,'U','3/3/2009') --<<dups 
INSERT INTO @HistoryTableNEW VALUES (1,'U','3/3/2009') --<<dups 
INSERT INTO @HistoryTableNEW VALUES (2,'I','5/5/2009') 
INSERT INTO @HistoryTableNEW VALUES (3,'I','7/7/2009') 
INSERT INTO @HistoryTableNEW VALUES (3,'U','8/8/2009') 

SELECT 
    m.MasterID,m.FirstName,m.LastName,h.LastAction,h.HistoryDate,h.HistoryID 
    FROM @MasterTable m 
     INNER JOIN (SELECT 
         MasterID,MAX(HistoryID) AS MaxHistoryID 
         FROM @HistoryTableNEW 
         GROUP BY MasterID 
        ) dt ON m.MasterID=dt.MasterID 
     INNER JOIN @HistoryTableNEW h ON dt.MasterID=h.MasterID AND dt.MaxHistoryID=h.HistoryID 

OUTPUT:

MasterID FirstName LastName LastAction HistoryDate    HistoryID 
----------- --------- -------- ---------- ----------------------- --------- 
1   AAA  aaa  U   2009-03-03 00:00:00.000 4 
2   BBB  bbb  I   2009-05-05 00:00:00.000 5 
3   CCC  ccc  U   2009-08-08 00:00:00.000 7 

(3 row(s) affected) 
0

如果歷史表中有一個主鍵(和所有的表都應該),您可以修改子查詢與以提取記錄更大(或更小)的倍數的PK值該匹配日期條件...

Select M.*, H.* 
    From Master M 
    Join History H 
     On H.PK = (Select Max(PK) From History 
        Where FK = M.PK 
         And Date = (Select Max(Date) From History 
            Where FK = M.PK)) 

至於性能,即可以通過添加適當的索引以這些表(History.Date,History.FK),但在一般情況下,這取決於具體的表中的數據加以處理分佈模式,子查詢會對性能產生不利影響。

相關問題