2013-04-30 71 views
2

我有具体结果上方的选择:如何获得数量范围内的最大顺序?

1 2 
1 3 
1 5 
1 6 
1 9 
1 10 
1 11 
1 13 
1 14 
1 16 
1 18 
1 20 
1 23 
1 24 
1 25 

我想找到的是发生在结果上最长的增加,由一链。

例如,我知道3是来自最后3个结果(23,24,25是3连续)的数字范围内的最大长度序列。

+0

它真的不清楚你问。例如,“顺序”是一个形容词,但你似乎将它用作名词,所以它很不确定你的意思。 – RBarryYoung 2013-04-30 16:14:41

+2

很难理解你在问什么。我们如何解释你的结果?你在寻找什么样的序列?你怎么知道3是'最大顺序插件'? – 2013-04-30 16:14:47

+4

我认为OP试图做的是在结果中找到连续的'增加1'的序列。例如,最后的23,24,25(这是3来自哪里,连续有3个做链) - 他们想要找出的是结果集中最长的这种链的时间长度。 – PhonicUK 2013-04-30 16:18:06

回答

5

一个序列将具有数字与顺序排序之间的差异是恒定的属性。在SQL的大多数方言中,您都有一个名为row_number()的函数,它可以分配连续的数字。

我们可以利用这个观察来解决问题:

select (num - seqnum), count(*) as NumInSequence 
from (select t.*, row_number() over (order by num) as seqnum 
     from t 
    ) t 
group by (num - seqnum) 

这给每个序列。要获得最大值,请使用max()与子查询或某个版本的limit/top。在SQL Server中,例如,你可以这样做:

select top 1 count(*) as NumInSequence 
from (select t.*, row_number() over (order by num) as seqnum 
     from t 
    ) t 
group by (num - seqnum) 
order by NumInSQuence desc 
+0

+1优雅而简洁! – 2013-04-30 18:00:24

1

使用这篇文章作为主查询: http://www.xaprb.com/blog/2006/03/22/find-contiguous-ranges-with-sql/

只需添加计算的差列,并选择MAX()。

SELECT MAX(seq.end - seq.start) 
FROM (
select l.id as start, 
    (
     select min(a.id) as id 
     from sequence as a 
      left outer join sequence as b on a.id = b.id - 1 
     where b.id is null 
      and a.id >= l.id 
    ) as end, 
from sequence as l 
    left outer join sequence as r on r.id = l.id - 1 
where r.id is null; 
) AS seq 
0

@戈登给出了一个明亮而又简洁的答案。不过,我认为递归实现也可能有用。下面是递归CTE的一个非常有用的文章:http://msdn.microsoft.com/en-us/library/ms186243(v=sql.105).aspx

-- This first CTE is unnecessary because you presumably already have 
-- your data. But I wanted to include it to make it easier test. 
WITH myNumbers AS (
SELECT * 
FROM (
     VALUES 
     (2), 
     (3), 
     (5), 
     (6), 
     (9), 
     (10), 
     (11), 
     (13), 
     (14), 
     (16), 
     (18), 
     (20), 
     (23), 
     (24), 
     (25) 
    ) AS x (num) 
), 
-- To get my sequences I recurse until there is no num + 1 in my set 
mySequences AS (
    -- Anchor member definition: Create the first invocation 
    SELECT v.num, 0 AS iteration, v.num AS previous, v.num AS start 
    FROM myNumbers v 
    UNION ALL 
    -- Recursive member definition: Recurse until value + 1 does not exist 
    SELECT s.num + 1, s.iteration + 1 AS iteration, s.num AS previous, s.start 
    FROM mySequences s -- Notice that we can reference the CTE within itself 
    JOIN myNumbers v 
     ON v.num = s.num + 1 
) 
-- I must increment by 1 because I chose to start my recursion at 0 
SELECT MAX(iteration + 1) 
FROM mySequences 

递归查询类似于编写

public int GetSequenceLength(int start, int iteration, int[] myNumbers) 
{ 
    if (myNumbers.Contains(start + 1)) 
    { 
     return GetSequenceLength(start + 1, iteration + 1, myNumbers); 
    } 
    return iteration; 
} 
foreach (var myNumber in myNumbers) 
{ 
    var sequenceLength = GetSequenceLength(myNumber, 0, myNumbers) + 1; 
    Console.WriteLine(myNumber + " : " + sequenceLength); 
} 
相关问题