2010-03-08 64 views
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的工作,如果它使任何區別)

回答

2

有沒有真正的 「優雅」 的方式。當你有這樣的組合分組查詢時,你將有子查詢或臨時表。

這將工作:

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 

你不應該在你想出雖然解決得下來。使用臨時表從來沒有看起來優雅,但它是高效的;如果您的原始兩步解決方案實際上比我的單步解決方案更快,我不會感到驚訝。 (你必須進行測試才能確定。)

+0

感謝您對錶現的關注。我嘗試了兩種方法,而且你是對的 - 臨時表方法的速度提高了1秒(總共83和84秒)!但是我會在任何一天(幾乎)任何一天對你的解決方案進行簡潔的說明...... – 2010-03-08 18:43:31