简体   繁体   中英

Selecting non-duplicates based on date column - SQL Server

I have two tables like this:

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   |

The idea being that some basic, immutable info about each client is stored in the first table, with more detailed info being stored in the second. When a client's data is edited, rather than editing their corresponding row in ClientRecordEntries, a completely new row is added (with a timestamp) so as to keep a record of all previous changes that have been made. So the current info for each client is the row in the second table that corresponds to their ID and has the most recent timestamp.

Eg for the Client with ID 5 lives at 743 Evergreen Terrace and his phone number is 0461238489, and his details have been been edited twice (so entered three times in all - rows 3, 6 and 7 of the second table.)

My question is, how can I JOIN the results of a query on the first table with the second table but remove all rows except the most current information per client? Eg say on the above example I want to select the current information for everyone called "Andy", so I'd want the result:

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

I'm guessing I'd want something like SELECT * FROM Clients JOIN ClientRecordEntries ON Clients.ID=ClientRecordEntries.cID WHERE Name='Andy'... and then something using MAX(SavedDate) but I'm stuck. Any suggestions?

(Yes I realise SELECT * will display more columns than I've typed above but I'm simplifying things.)

I'm using SQL Server if it makes a difference.

By the term removing duplicates , if you mean that you only want to hide duplicates values during projection, you can use Window Functions on this,

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

Try this. You can use CTE and ROW_NUMBER() to achieve this.

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

Unless you have a little number of clients, you should add a flag in your table ClientRecordEntries to indicate which row is the most recent for each client for performance reason and also add an index covering this flag and the cId columns.

As it is very rare to have the need to take a look at this old information, another solution would be to use a third table to old this old information. Often, there will be a single table to hold all the older informations from the other tables; along with some other information like the time of edition and the user who have done it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM