半复数聚合选择语句混淆

时间:2010-03-08 18:10:59

标签: sql sql-server tsql aggregate-functions

好吧,这个问题有点复杂,所以请耐心等待。

我有一张满是数据的表格。其中一个表列是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)的正确连接可以做到这一点,就像自我加入一样......但是你如何用{{1}做到这一点条款?我无法找到使查询执行的正确语法。

我对SQL很新,所以很可能我错过了一些明显的东西。有什么建议吗?

(在T-SQL中工作,如果有任何区别的话)

1 个答案:

答案 0 :(得分:2)

没有真正“优雅”的方式。如果您有这样的Group By查询组,那么您将拥有子查询或临时表。

这将有效:

Select ID, A.PersonID, A.StoreID, Data1, Data2, A.EntryDate
From ExampleTable As A
Inner Join
    (select PersonID, StoreID, max(EntryDate) As EntryDate
    from ExampleTable
    group by PersonID, StoreID, dbo.dayof(EntryDate)) As B
  On ExampleTable.PersonID = B.PersonID 
    And ExampleTable.StoreID = B.StoreID 
    And ExampleTable.EntryDate = B.EntryDate

你不应该对你提出的解决方案太过贬低。使用临时表永远不会看起来优雅,但效率很高;如果您的原始两步解决方案实际上比我的一步解决方案更快,我不会感到惊讶。 (你必须进行测试才能确定。)