如果不知道数据库产品,很难提供答案。
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
)
)
)
你会注意到我的答案中的一些注意事项。这表明我们需要更多信息:
- 什么数据库产品和版本?
- 桌子上是否有一个auto_incrementing唯一键?
- 该级别如何适合你想要的结果? (请扩展您的示例数据以包含边缘案例)。
- 如果当前日期和时间早于有效日期到期日期,应该发生什么情况?
编辑
现在我们知道你使用的是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的“顶部”值。
对于什么数据库? – 2010-08-09 00:20:07
@ sqllearner190 - 表有一个主键,如auto_increment或标识列吗? – Thomas 2010-08-09 00:23:46
@ sqllearner190 - 您能否在您的示例数据中演示需要项目#2的第二个条件的情况? – Thomas 2010-08-09 00:26:26