【问题标题】:Selecting non-duplicates based on date column - SQL Server根据日期列选择非重复项 - SQL Server
【发布时间】:2013-03-06 09:16:51
【问题描述】:

我有两张这样的表:

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 对应且具有最新时间戳的行。

例如ID 为 5 的客户住在 743 Evergreen Terrace,他的电话号码是 0461238489,他的详细信息已被编辑两次(因此总共输入了 3 次 - 第二个表的第 3、6 和 7 行。)

我的问题是,如何将第一个表的查询结果与第二个表连接,但删除除每个客户端的最新信息之外的所有行?例如。在上面的例子中说,我想为每个名为“Andy”的人选择当前信息,所以我想要结果:

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 Server。

【问题讨论】:

    标签: sql sql-server select join


    【解决方案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
    

    【讨论】:

    • 抱歉,我不知道您所说的“投影期间”是什么意思。
    • @GeorgeMillo 这是投影——意思是选择。
    • 是的,很抱歉标题可能措辞不当,我不想删除重复的条目,我只是不想让它们被选中。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      除非您的客户端数量很少,否则您应该在表 ClientRecordEntries 中添加一个标志,以指示出于性能原因对于每个客户端而言哪一行是最新的,并添加一个涵盖该标志和 cId 列的索引。

      由于很少需要查看这些旧信息,另一种解决方案是使用第三个表来旧这些旧信息。通常,会有一个表来保存其他表中的所有旧信息;以及其他一些信息,例如版本时间和完成版本的用户。

      【讨论】:

        猜你喜欢
        • 2019-06-28
        • 2023-03-15
        • 2019-03-29
        • 2018-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多