2013-04-30 51 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); 
} 
相關問題