好吧,这个问题有点复杂,请耐心等待。半复杂集合选择语句混淆
我有一张充满数据的表格。其中一个表列是EntryDate。每天可以有多个条目。但是,我想要选择所有日期中最新条目的所有行,并且要选择所有表中的所有列。
其中一列是一个唯一标识符列,但它不是主键(我不知道它为什么存在;这是一个非常旧的系统)。为了演示的目的,假设表格如下所示:
create table ExampleTable (
ID int identity(1,1) not null,
PersonID int not null,
StoreID int not null,
Data1 int not null,
Data2 int not null,
EntryDate datetime not null
)
主键在PersonID和StoreID上,逻辑上定义了唯一性。
现在,就像我所说的,我想要选择在特定日期(对于每个Person-Store组合)最新条目的所有行。这很容易:
--Figure 1
select PersonID, StoreID, max(EntryDate)
from ExampleTable
group by PersonID, StoreID, dbo.dayof(EntryDate)
其中dbo.dayof()是一个简单的函数,它可以从日期时间中去除时间分量。但是,这样做会损失其余的列!我不能简单地包含其他列,因为那样我就不得不group by
他们,这会产生错误的结果(尤其是因为ID是唯一的)。
我发现了一个肮脏的黑客会做我想做的,但必须有一个更好的办法 - 这是我目前的解决方案:
select
cast(null as int) as ID,
PersonID,
StoreID,
cast(null as int) as Data1,
cast(null as int) as Data2,
max(EntryDate) as EntryDate
into #StagingTable
from ExampleTable
group by PersonID, StoreID, dbo.dayof(EntryDate)
update Target set
ID = Source.ID,
Data1 = Source.Data1,
Data2 = Source.Data2,
from #StagingTable as Target
inner join ExampleTable as Source
on Source.PersonID = Target.PersonID
and Source.StoreID = Target.StoreID
and Source.EntryDate = Target.EntryDate
这让我正确的数据在#StagingTable
但是,好了,看它!用空值创建一个表,然后进行更新以获取值 - 当然有更好的方法来做到这一点?一个单一的声明,将首次给我所有的价值?
我相信,原始select
(图1)上的正确连接可以实现诀窍,就像自连接或其他东西一样......但您如何使用group by
子句做到这一点?我无法找到正确的语法来执行查询。
我很新的SQL,所以很可能我错过了一些明显的东西。有什么建议么?
(以T-SQL的工作,如果它使任何区别)
感谢您对表现的关注。我尝试了两种方法,而且你是对的 - 临时表方法的速度提高了1秒(总共83和84秒)!但是我会在任何一天(几乎)任何一天对你的解决方案进行简洁的说明...... – 2010-03-08 18:43:31