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
答案 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
)
)
)
你会在我的回答中注意到一些警告。这表明我们需要更多信息:
修改强>
现在我们知道您正在使用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”值。