2011-10-13 64 views
1

我試圖從sql服務器數據庫中的任意n個鏈接元組中選擇最大ID - 我們正在爲應用程序中的一些數據集編寫升級腳本,並且需要了解可用的最高升級是基於當前數據的版本。例如,使用下面的簡化表「版本」:如何從n個鏈接的元組中選擇最大值

oldVersionId newVersionId 
1    2 
2    3 
3    4 
10    11 

我們知道我們是第1版,並希望得到的最高版本,在那裏,我們可以升級到;在這種情況下返回4,而不是11.我們可以在任何給定時間有0-n個可升級版本。我不是一個SQL wiz,然後只能想到用可變數量的鏈接選擇要查詢的:

select newVersion from versions where oldVersionId = (select newVersion from versions where oldVersionId = 1) 

但它不是一個n個編號的搜索,並且將無法正常返回,如果元件的數量較大或者小於給定值。 sql是否能夠執行這樣的查詢,以及我應該查看哪些元素/關鍵字來編寫一個?

解決方案:

你每天都學到新的東西 - 我所需要的兩個答案的混合體。原來,sql可以使用類似於樹的子/父鏈接來查詢數據集,而我在OO語言中更方便。

在sql server中,您可以使用別名表設置遞歸樹行走呼叫。您需要一個錨點然後遞歸位。第一次調用是錨點,我可以使用表中的任何值或值的列表等。第二個select調用只是說使用表的其餘部分進行掃描。

下面是語法:

--Create the new alias (s) 
;with s (oldVersionId, newVersionId) as 
(
    --set up the anchor node, 
    select oldVersionId, newVersionId from @t 
    where oldVersionId = 1 

    -- join it to the rest of the table, denoting that we only want nodes 
    -- where the old version is represented as a new version later 
    union all 
    select t.oldVersionId, t.newVersionId from @t as t 
    inner join s on t.oldVersionId = s.newVersionId 
) 
--Return the max value from the nodes I collected 
select max(s.newVersionId) from s 
+0

是不是11而不是4? – Bala

+0

好問題 - 不,應該是4。有沒有辦法使用鏈接表中的任何值,1到10。我們可以將1到4連接到2和3,所以4是正確的。 – Noah

+0

好的。我現在明白了.. CTE可以使用。 – Bala

回答

0

您有效地需要確定一個鏈表的最後一個節點 - 在我看來,最好的辦法是使用熱膨脹係數的遞歸功能,讓你的「最大」版本,但我對CTE不夠熟悉,無法正常工作。

下面得到正確的答案,但只是因爲我知道這個特定的虛擬表預先需要多少鏈接;因此,不理想。

CREATE TABLE #temp (
oldversionID SMALLINT, 
newversionID SMALLINT) 

INSERT INTO #temp 
VALUES (1,2) 
INSERT INTO #temp 
VALUES (2,3) 
INSERT INTO #temp 
VALUES (3,4) 
INSERT INTO #temp 
VALUES (10,11); 


select t1.oldversionID, t3.newversionID from #temp t1 
inner join #temp t2 
on t1.newversionId = t2.oldversionID 
inner join #temp t3 
on t2.newversionId = t3.oldversionID 
2

這裏是CTE的解決方案 - 環通的數據,同時我們對oldVersionId = newVersionId下一場比賽:

declare @t table (
    oldVersionId int, 
    newVersionId int) 

insert into @t values (1,2) 
insert into @t values (2,3) 
insert into @t values (3,4) 
insert into @t values (10,11) 
insert into @t values (11,12) 
insert into @t values (14,15) 

declare @startVer int 
set @startVer = 1 

;with s (oldVersionId, newVersionId) as 
(
    select top 1 oldVersionId, newVersionId from @t 
    where oldVersionId = @startVer 
    union all 
    select t.oldVersionId, t.newVersionId from @t as t 
    inner join s on t.oldVersionId = s.newVersionId 
) 
select max(s.newVersionId) 
from s 
option (maxrecursion 0) 

這裏是解決方案,而CTE - 尋找具有newVersionId的最後一條記錄等於1(第一版)加上這個版本的不可思議的更新總和:

select max(t1.newVersionId) 
from @t t1 
where t1.oldVersionId >= @startVer 
and t1.newVersionId = @startVer + (
    select sum(newVersionId - oldVersionId) 
    from @t 
    where 
     oldVersionId >= @startVer and 
     oldVersionId < t1.newVersionId) 
+0

這看起來非常接近,但我無法提供oldVersionId來使用;如果我要從版本10升級,我需要的結果是11.我正在玩的語法,看看我無法弄清楚。 – Noah

+0

好吧,我已經更新了代碼 - 添加了startVer參數和更多示例行。如果你設置@startVer = 10,那麼你會得到12 – sarh

相關問題