2009-08-26 54 views
2

我有一個名爲「句子」具有以下字段的表:訂購基於字段指向同一個表的查詢

ID   <--- OK 
NextID  <--- FK To ID 
Text 

所以,如果我有以下記錄:

*ID*   *NextID*   *Text* 
1    12    The quick 
3    40    jumps over 
5    null    lazy dog. 
12    3     brown fox 
40    5     the 

如果我知道序列的開頭是ID = 1的記錄,是否有一種方法可以根據NextID的序列來排序查詢。與上面的例子中,預期的結果應該是...

The quick 
brown fox 
jumps over 
the 
lazy dog. 

我找無論是T-SQL語句/秒或以某種方式做到這一點使用LINQ。提前致謝!

+0

一個sql鏈表...有趣! – Joel 2009-08-26 19:22:45

+0

如果有人使用oracle想要做同樣的事情,我會提到oracle有一個「Connect By」子句,它可以很簡單地解決這個問題,也可以用於更復雜的樹結構。 – 2010-01-12 19:36:32

回答

3

試試這個:

declare @YourTable table (RowID int primary key, NextID int, TextValue varchar(50)) 

INSERT INTO @YourTable VALUES (1 , 12 ,'The quick') 
INSERT INTO @YourTable VALUES (3 , 40 ,'jumps over') 
INSERT INTO @YourTable VALUES (5 , null,'lazy dog.') 
INSERT INTO @YourTable VALUES (12, 3 ,'brown fox') 
INSERT INTO @YourTable VALUES (40, 5 ,'the') 

;with cteview as (
SELECT * FROM @YourTable WHERE RowID=1 
UNION ALL 
SELECT y.* FROM @YourTable y 
    INNER JOIN cteview c ON y.RowID=c.NextID 
) 
select * from cteview 
OPTION (MAXRECURSION 9999) --go beyond default 100 levels of recursion to 9999 levels 

OUTPUT:

RowID  NextID  TextValue 
----------- ----------- -------------------------------------------------- 
1   12   The quick 
12   3   brown fox 
3   40   jumps over 
40   5   the 
5   NULL  lazy dog. 

(5 row(s) affected) 
+0

這將最多執行100次遞歸,然後您將不得不配置SQL Server以使遞歸深度更高。 – 2009-08-26 19:46:10

+0

您不必更改服務器默認值100.如果您在cteview_之後的_select *之後添加_OPTION(MAXRECURSION n)_,其中n可以介於0和32,767之間的遞歸級別(零無限制) – 2009-08-26 19:52:28

+0

這看起來很漂亮整潔,但我想知道如果我可以將其轉換成LINQ聲明。 – Jaime 2009-08-26 19:53:50

0

LINQ答案:

table.OrderBy(sentence => sentence.NextID); 

編輯:我希望我正確地回答了這一次:

class Sentence 
{ 
    public int Id; 
    public int? NextId; 
    public string Text; 
    public Sentence(int id, int? nextId, string text) 
    { 
     this.Id = id; 
     this.NextId = nextId; 
     this.Text = text; 
    } 
} 

var Sentences = new [] { 
    new Sentence(1, 12, "This quick"), 
    new Sentence(3, 40, "jumps over"), 
    new Sentence(5, null, "lazy dog."), 
    new Sentence(12, 3, "brown fox"), 
    new Sentence(40, 5, "the"), 
}; 

Func<int?, string> GenerateSentence = null; 
GenerateSentence = (id) => id.HasValue? Sentences 
    .Where(s => s.Id == id.Value) 
    .Select(s => s.Text + " " + GenerateSentence(s.NextId)) 
    .Single() : string.Empty; 

Console.WriteLine(GenerateSentence(1)); 
+2

這不會給你的結果... 懶狗。 棕色狐狸 的 快速 躍過 ???? – Jaime 2009-08-26 19:40:42

+0

你說得對,我誤解了這個問題。 – 2009-08-26 20:58:52

+0

只要它不是一個循環鏈表,它應該工作。 – 2009-08-27 00:15:16

0

如果您使用的是LINQ to SQL/Entities,那麼生成的Sentence類應該具有您提及的所有屬性,以及來自外鍵的下一句(我們稱之爲NextSentence)的實體引用。

然後,你可以這樣做:

Sentence s = Sentences.First(); 
StringBuilder sb = new StringBuilder(); 
do { sb.Append(s.Text); s = s.NextSentence; } while (s != null); 

sb.ToString()將有你的答案。