1

好吧,这个问题有点复杂,请多多包涵。

我有一个充满数据的表。表列之一是 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 中工作,如果有什么不同的话)

4

1 回答 1

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

不过,您不应该对您提出的解决方案过于失望。使用临时表看起来并不优雅,但它很有效;如果您最初的两步解决方案实际上比我的一步解决方案更快,我不会感到惊讶。(你必须测试才能确定。)

于 2010-03-08T18:22:04.280 回答