选择具有更多条件的最新记录

时间:2010-08-09 00:12:34

标签: sql sql-server-2008 record

ID    Level Effective Date  ExpirationDate
000012-12     2 12/01/2005  NULL
000012-12    1    12/01/2005  NULL
000012-12    2    12/01/2005  01/01/2009
000012-A12    2 10/01/1994  11/30/2005
000012-A12    2 01/01/1999  11/30/2005
000012-A12    2 09/01/2001  11/30/2005
000012-A12    1 12/01/2005  12/31/2007

仅提取最新的记录。这意味着在上面的场景中 截止日期 - 如果null记录仍处于活动状态            如果大于当前时间戳,则其未来的到期日期,这意味着仍然有效            如果小于当前时间戳,则终止。
目前大多数是最活跃或最新终止的记录。如果它已激活且已终止,则仅显示活动。其他人最后终止了记录。

一个ID可以有2行用于相同的生效日期和exp日期,但有多个级别。因此,在这种情况下,我们只需要为第一级选择1条记录。

因此,根据以下数据集,预期输出

输出

000012-12    1   12/01/2005  NULL
000012-A12  2   12/01/2005  01/01/2009

请帮忙

托马斯。请查看以下数据集。

Insert #Test( Id, Level, EffectiveDate, ExpirationDate ) Values ('000872-A24',1,'1994-10-01',NULL); 
Insert #Test( Id, Level, EffectiveDate, ExpirationDate ) Values ('000872-A24',1,'1999-01-01',NULL);  
Insert #Test( Id, Level, EffectiveDate, ExpirationDate ) Values ('000872-A24',2,'2001-09-01',NULL ); 
Insert #Test( Id, Level, EffectiveDate, ExpirationDate ) Values ('000872-A24',1,'2003-01-01','2007-12-31'); 

运行查询时,应该给出

  

000872-A24 2 09/01/2001 NULL

但现在它返回

  

000872-A24 1 01/01/2003 12/31/2007

1 个答案:

答案 0 :(得分:1)

在不知道数据库产品的情况下很难提供答案。

1. if there is no auto_increment/identity column 
2. and if there is no other primary key (which is a bad idea obviously) 
3. and if the given database product supports `CURRENT_TIMESTAMP` (each DBMS will likely have some equivalent to the current date and time) 
4. and if the target date by which you measure "latest" is the current date and time


Select Id, Level
From Table As T
Where T. EffectiveDate =    (
                            Select Max(T2.EffectiveDate)
                            From Table As T2
                            Where T2.ID = T.ID
                                And ( T2.EffectiveDate Is Null
                                    Or (
                                        CURRENT_TIMESTAMP >= T2.EffectiveDate
                                        And CURRENT_TIMESTAMP <= T2.ExpirationDate
                                        )
                                    )
                            )   

你会在我的回答中注意到一些警告。这表明我们需要更多信息:

  1. 什么数据库产品和版本?
  2. 桌子上是否有auto_incrementing,唯一键?
  3. 等级如何适合您想要的结果? (请扩展您的示例数据以包含边缘情况)。
  4. 如果当前日期和时间早于有效期为空的生效日期,应该怎么办?
  5. 修改

    现在我们知道您正在使用SQL Server 2008,这使解决方案更容易:

    If object_id('tempdb..#Test') is not null
        Drop Table #Test;
    GO
    Create Table #Test (
                        PkCol int not null identity(1,1) Primary Key
                        , Id varchar(50) not null
                        , Level int not null
                        , EffectiveDate datetime not null
                        , ExpirationDate datetime null
                        );
    
    Insert #Test( Id, Level, EffectiveDate, ExpirationDate ) Values ('000012-12',2,'12/01/2005',NULL);
    Insert #Test( Id, Level, EffectiveDate, ExpirationDate ) Values ('000012-12',1,'12/01/2005',NULL); 
    Insert #Test( Id, Level, EffectiveDate, ExpirationDate ) Values ('000012-12',2,'12/01/2005','01/01/2009');
    Insert #Test( Id, Level, EffectiveDate, ExpirationDate ) Values ('000012-A12',2,'10/01/1994','11/30/2005');
    Insert #Test( Id, Level, EffectiveDate, ExpirationDate ) Values ('000012-A12',2,'01/01/1999','11/30/2005');
    Insert #Test( Id, Level, EffectiveDate, ExpirationDate ) Values ('000012-A12',2,'09/01/2001','11/30/2005');
    Insert #Test( Id, Level, EffectiveDate, ExpirationDate ) Values ('000012-A12',1,'12/01/2005','12/31/2007');
    
    With Items As
        (
        Select PkCol, Id, Level, EffectiveDate, ExpirationDate
            , Row_Number() Over (   Partition By Id
                                    Order By EffectiveDate Desc, Coalesce(ExpirationDate,'99991231') Desc, Level Asc ) As Num
        From #Test
        )
    Select PkCol, Id, Level, EffectiveDate, ExpirationDate
    From Items
    Where Num = 1
    

    在您的示例输出中,您的组合('000012-A12',2,'12/01/2005','01/01/2009')未显示在原始数据中。

    我正在使用SQL Server 2005中添加的两个功能:公用表表达式和排名功能。公用表表达式Item的作用类似于就地视图或查询。排名函数Row_Number是真正的魔法发生的地方。顾名思义,它返回由Order By子句排序的顺序数字列表。但是,它还会重新开始每个Id值的编号(即Partition By位)。通过对Num = 1进行过滤,我将为每个Id返回“top”值。