下面是一個快速腳本,用於創建臨時表格,填充數據並向您展示如何處理您遇到的問題。讓我先說,這種東西有時最好留給業務邏輯層。另外,我不確定您的描述是否準確,因爲似乎存在一些不一致之處。據說,我希望你能拿走如何解決你的問題,把它分解成部分並解決它。不要擔心事先優化,只需編寫乾淨的邏輯代碼即可。優化器會告訴你,如果你犯了什麼錯誤。這是假設的SQL Server 2008:
declare @Tests table
(
ID int,
Name varchar(100)
)
declare @TestVersions table
(
TestID int,
Version int,
IsActive bit
)
declare @TestSessions table
(
TestID int,
TestVersion int,
UserID varchar(100),
Iteration int,
Completed bit,
CompletionDate date
)
insert into @Tests
select 1, 'one' union all
select 2, 'two' union all
select 3, 'three' union all
select 4, 'four' union all
select 5, 'five'
insert into @TestVersions
select 1, 1, 0 union all
select 2, 1, 1 union all
select 3, 1, 0 union all
select 4, 1, 0 union all
select 5, 1, 1 union all
select 1, 2, 0 union all
select 2, 2, 0 union all
select 3, 2, 1 union all
select 4, 2, 0 union all
select 1, 3, 1 union all
select 2, 3, 1
insert into @TestSessions
select 1, 1, 'a', 1, 1, GETDATE()-101 union all
select 2, 1, 'b', 1, 1, GETDATE()-11 union all
select 3, 1, 'c', 1, 0, null union all
select 4, 1, 'd', 1, 1, GETDATE()-103 union all
select 5, 1, 'e', 1, 1, GETDATE()-101 union all
select 1, 2, 'f', 1, 1, GETDATE()-15 union all
select 2, 2, 'g', 1, 0, null union all
select 3, 2, 'h', 1, 1, GETDATE()-17 union all
select 4, 2, 'i', 1, 0, null union all
select 1, 3, 'j', 2, 1, GETDATE()-109 union all
select 2, 3, 'k', 2, 1, GETDATE()-101 union all
select 2, 1, 'l', 3, 1, GETDATE()-120 union all
select 3, 1, 'm', 1, 1, GETDATE()-11 union all
select 4, 1, 'n', 1, 1, GETDATE()-140 union all
select 5, 1, 'a', 1, 0, null union all
select 1, 2, 'b', 1, 1, GETDATE()-160 union all
select 2, 2, 'c', 2, 0, null union all
select 3, 2, 'd', 1, 1, GETDATE()-17 union all
select 4, 2, 'e', 1, 0, null union all
select 1, 3, 'f', 2, 1, GETDATE()-4 union all
select 2, 3, 'g', 3, 1, GETDATE()-101
select Id
,Name
,Version
from @Tests t
inner join
@TestVersions v on t.ID = v.TestID
-- any test with a session with completed = false
where exists
(select *
from @TestSessions s1
where s1.Completed = 0
and s1.TestID = t.ID
and s1.TestVersion = v.Version
)
or (
-- any max version of a test which has no sessions
not exists
(select *
from @TestSessions s1
where s1.TestID = t.ID
and s1.TestVersion = v.Version
)
and v.Version =
(select MAX(Version)
from @TestVersions v2
where v2.TestID = t.ID
)
)
or (
-- no uncompleted sessions
not exists
(select *
from @TestSessions s1
where s1.Completed = 0
and s1.TestID = t.ID
and s1.TestVersion = v.Version
)
-- we're already inner joining to versions, so we just need to check IsActive
and IsActive = 1
-- the most recent completion date is at least 30 days ago (not quite 30 days ago but i'm lazy)
and GETDATE() - 30 <=
(select MAX(CompletionDate)
from @TestSessions s2
where s2.TestID = t.ID
and s2.TestVersion = v.Version
)
-- not sure what you mean by "return", but I'm sure you can figure out how to project what you need
)
你覺得什麼是 '不一致'? – SonOfPirate 2011-04-10 13:09:03
至於「返回」,我的意思是我需要該記錄的版本列中的最高值。在哪裏變得麻煩的是,我可以創建一個新版本的Test,同時前一個版本的TestSession仍然處於打開狀態(Complete爲false)。當TestSession完成時(Complete爲true),我需要返回新的(更高的)版本,而不是與最後一個(最近的)TestSession關聯的版本。 – SonOfPirate 2011-04-10 13:11:25
我也認爲第三個子句中的子查詢('no uncompleted sessions')可能有缺陷。如果TestSessions中不存在記錄,則不存在與Completed = 0也會導致真實條件。我在考慮用Completed = 1檢查'exists'來測試以前完成的會話會更好。 – SonOfPirate 2011-04-10 13:41:37