2011-10-13 60 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

相关问题