2013-03-06 119 views
0

我有兩個表是這樣的:選擇非重複基於日期列 - SQL服務器

Clients     
ID | Name | DOB  | etc... 
1 | Andy | 26/12/90 | 
2 | Bob | 27/10/93 | 
3 | Callum | 11/12/97 | 
4 | Dave | 06/01/64 | 
5 | Andy | 01/06/89 | 

ClientRecordEntries 
ID | cID | DateSaved  | Address    | Phone Number | Blah blah blah... 
1 | 1 | 06/03/13 03:01 | 1 High Street   | 0754812374 | 
2 | 1 | 06/03/13 04:05 | 1 High Street   | 0854123474 | 
3 | 5 | 06/03/13 04:23 | 742 Evergreen Terrace | 0548162384 | 
4 | 4 | 06/03/13 03:27 | 5 Spooner St   | 0512348455 | 
5 | 3 | 06/03/13 05:03 | 6 Cromwell Avenue  | 0745289324 | 
6 | 5 | 06/03/13 05:04 | 743 Evergreen Terrace | 0548162384 | 
7 | 5 | 06/03/13 05:17 | 743 Evergreen Terrace | 0461238489 | 
8 | 2 | 06/03/13 05:18 | 45 High Street  | 0682374988 | 

的想法是,大約每個客戶的一些基本的,不可變的信息存儲在第一個表,更詳細的信息存儲在第二個。在編輯客戶端數據時,不是編輯ClientRecordEntries中的相應行,而是添加一個全新的行(帶有時間戳),以便記錄所有以前所做的更改。因此,每個客戶端的當前信息是第二個表中與其ID相對應且具有最近時間戳的行。

E.g.身份證號碼爲5的客戶住在Evergreen Terrace 743號,他的電話號碼是0461238489,他的詳細資料已經被編輯了兩次(所以在第二張表的第3,6和7行所有行中都輸入了三次。)

我的問題是,如何將第一個表上的查詢結果與第二個表聯接起來,但刪除除了每個客戶端最新信息之外的所有行?例如。說上述例子我想選擇爲大家稱爲「安迪」的最新信息,所以我想要的結果:

Name | DOB  | Address    | Phone Number | etc... 
Andy | 26/12/90 | 1 High Street  | 0854123474 | 
Andy | 01/06/89 | 743 Evergreen Terrace | 0461238489 | 

我猜我會希望像SELECT * FROM Clients JOIN ClientRecordEntries ON Clients.ID=ClientRecordEntries.cID WHERE Name='Andy'...的東西,然後用東西MAX(SavedDate)但我卡住了。有什麼建議麼?

(是的,我知道SELECT *將顯示更多的列比我打字以上,但我簡化了的東西。)

我使用SQL服務器,如果它的確與衆不同。

回答

1

術語刪除重複,如果你的意思,你只需要在投影過程中隱藏重複值,你可以使用這個窗口函數,

WITH records AS 
(
    SELECT ID,cID,DateSaved,Address ,[Phone Number], 
      ROW_NUMBER() OVER (PARTITION BY cid ORDER BY DateSaved DESC) rn 
    FROM ClientRecordEntries 
) 
SELECT a.*, DateSaved,Address ,[Phone Number] 
FROM Clients a 
     INNER JOIN records b 
      ON a.ID = b.cid 
WHERE b.rn = 1 
+0

對不起,但我不知道你在'投影期間'的意思。 – GMA 2013-03-06 09:22:01

+0

@GeorgeMillo它的投影 - 意思選擇。 – 2013-03-06 09:22:45

+0

對不起,標題可能表達不佳,我不想刪除重複的條目,我只是不希望他們被選中。 – GMA 2013-03-06 09:24:45

1

試試這個。您可以使用CTEROW_NUMBER()來實現此目的。

WITH CTE 
AS 
( 
    SELECT *, 
     ROW_NUMBER() OVER (PARTITION BY CID ORDER BY DateSaved DESC) RN 
    FROM ClientRecordEntries 
) 

SELECT * 
FROM Clients C 
INNER JOIN CTE CT 
ON CT.CID = C.ID 
WHERE C.NAME = 'Andy' 
AND RN = 1 

SQL FIDDLE DEMO

1

除非你有客戶端的一個小數目,你應該在你的表ClientRecordEntries添加一個標誌,表示該行是最近的爲每一個客戶對性能的原因,也添加覆蓋此標誌和cId列的索引。

由於需要查看這些舊信息是非常罕見的,另一個解決方案是使用第三個表來老化這些舊信息。通常,會有一張表格來存放來自其他表格的所有舊信息;以及其他一些信息,比如編輯時間和完成它的用戶。