选择非重复基于日期列 - SQL服务器

问题描述:

我有两个表是这样的:选择非重复基于日期列 - 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服务器,如果它的确与众不同。

术语删除重复,如果你的意思,你只需要在投影过程中隐藏重复值,你可以使用这个窗口函数,

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

试试这个。您可以使用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

除非你有客户端的一个小数目,你应该在你的表ClientRecordEntries添加一个标志,表示该行是最近的为每一个客户对性能的原因,也添加覆盖此标志和cId列的索引。

由于需要查看这些旧信息是非常罕见的,另一个解决方案是使用第三个表来老化这些旧信息。通常,会有一张表格来存放来自其他表格的所有旧信息;以及其他一些信息,比如编辑时间和完成它的用户。