2010-12-08 64 views
3

我會採取C#和VB.NET的建議。LINQ to SQL查詢父級和計數子級別

我正在使用LINQ來查詢數據。我試圖查詢父項並計數子標籤。

這裏是我的標籤表列:

TagId (int primary) 
TagName 
ParentId (int Allow NULL referred to TagId column) 

下面是一些樣本數據:

TagId, TagName, ParentId 

1, Web Design, NULL 
2, HTML, 1 
3, Programming, NULL 
4, CSS 3, 1 

問題1:在我的查詢結果,我想查詢所有父標籤用的總和兒童標籤。像下面這樣:

Web Design (2 sub tags) 
Programming (0 sub tags) 

問題2:如果孩子標籤也有其自己的子標籤

下面是一些樣本數據:

TagId, TagName, ParentId 

1, Web Design, NULL 
2, HTML, 1 
3, Programming, NULL 
4, CSS 3, 1 
5, HTML 4, 2 
6, HTML 5, 2 

所需的查詢結果:

Web Design (4 sub tags) 
Programming (0 sub tags) 

問題2是可選的bu如果你也提出一些建議,這將是非常好的。謝謝。

+0

您是否找到解決該問題的方法?你試過我的解決方案嗎? – 2010-12-13 15:19:23

+0

還沒有,我仍然環顧四周。有一篇關於LINQ AsHierarchy()擴展方法的文章,由Stefan Cruysberghs @ http://www.scip.be/index.php?Page=ArticlesNET23無論如何,我也會嘗試你的建議。任何VB.NET版本的建議?無論如何,我會嘗試將其轉換爲VB.NET – Narazana 2010-12-15 01:47:38

+0

我更新了我的答案,提供了非常好的解決方案。 – abatishchev 2011-01-21 08:41:50

回答

0

定義:

class Tag 
{ 
    public int Id { get; set; } 
    public string TagName { get; set; } 

    public int? ParentId { get; set; }  

    public IEnumerable<Tag> Children { get; set; } 
} 

數據:

int id = 0; 
var tags = new[] 
{ 
    new Tag 
    { 
     Id = ++id, 
     TagName = "Parent", 
     ChildNodes = new[] 
     { 
      new Tag { TagName = "Child1", Id = ++id, ParentId = 1 }, 
      new Tag { TagName = "Child2", Id = ++id, ParentId = 1 } 
     } 
    } 
    new Tag 
    { 
     Id = ++id, 
     TagName = "NoChildren" 
    } 
}; 

1, Parent, null 
2, Child1, 1 
3, Child2, 1 
4, NoChildren, null 

代碼:

var q = from tag in tags 
     where tag.ParentId == null 
     select new 
     { 
      Name = tag.TagName, 
      ChildrenCount = tag.Children.Count() 
     }; 

foreach (var entry in q) 
{ 
    Console.WriteLine("{0} ({1} sub tags)", entry.Name, entry.ChildrenCount); 
} 

輸出:

Parent (2 sub tags) 
NoChildren (0 sub tags) 

在複雜的層次結構的情況下,讓所有的子節點遞歸地使用可以使用未來的擴展方法:

public static IEnumerable<Tag> GetChildTags(this Tag tag) 
{ 
    var children = tag.Children ?? Enumerable.Empty<Tag>(); 
    return children.SelectMany(c => GetChildTags(c)).Concat(children); 
} 
0

好的,最簡單的方法是創建一個簡單的結構,如果他們有父母,則連接標籤,然後迭代兒童中心以產生每個標籤的計數。

class Tag 
{ 
    public Tag(int id, int? parentId, string tag) 
    { 
     Id = id; 
     ParentId = parentId; 
     TagName = tag; 
    } 

    public int Id { get; set; } 
    public int? ParentId { get; set; } 
    public string TagName { get; set; } 
} 

class TagNode 
{ 
    public Tag Node { get; set; } 
    public IList<TagNode> ChildNodes { get; set; } 
    public int ChildNodeCount() 
    { 
     int count = 0; 
     if (ChildNodes != null) 
     { 
      foreach (var node in ChildNodes) 
      { 
       count += node.ChildNodeCount(); 
      } 
      count += ChildNodes.Count; 
     } 
     return count; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var tags = new List<Tag>(); 
     tags.Add(new Tag(1, null, "Web design")); 
     tags.Add(new Tag(2, null, "Programming")); 
     tags.Add(new Tag(3, 1, "HTML")); 
     tags.Add(new Tag(4, 1, "CSS 3")); 
     tags.Add(new Tag(5, 3, "HTML 4")); 
     tags.Add(new Tag(6, 3, "HTML 5")); 

     IList<TagNode> nodes = tags.Select(y => new TagNode { Node = y, ChildNodes = new List<TagNode>() }).ToList(); 
     foreach (var node in nodes) 
     { 
      if (node.Node.ParentId.HasValue) 
       ConnectNodeToParent(nodes, node); 
     } 

     // print all nodes 
     Console.WriteLine("=== ALL NODES ==="); 
     nodes.ToList().ForEach(PrintNode); 

     // print root nodes 
     Console.WriteLine(Environment.NewLine + "=== ROOT NODES ==="); 
     nodes.Where(y => y.Node.ParentId.HasValue == false).ToList().ForEach(PrintNode); 

     Console.ReadLine(); 
    } 

    private static void PrintNode(TagNode node) 
    { 
     Console.WriteLine("Tag id: {0}, Tag name: {1}, Tag count: {2}", node.Node.Id, node.Node.TagName, node.ChildNodeCount()); 
    } 

    private static void ConnectNodeToParent(IList<TagNode> nodes, TagNode node) 
    { 
     var parentNode = nodes.Where(y => y.Node.Id == node.Node.ParentId.Value).Single(); 
     parentNode.ChildNodes.Add(node); 
    } 
} 

通過上面的代碼,您可以獲得每個標記的信息,而不僅僅是「父」標記。

1
public static IEnumerable<T> SelectDescendents<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> selector) 
{ 
    foreach(var item in source) 
    { 
    yield return item; 
    foreach(T item2 in SelectDescendents(selector(item), selector)) 
    yield return item2; 
    } 
} 

編輯: 用法:

Tags.where(t => t.tagID == 1).SelectDescendents(d => 
    Tags.where(t.parentID == d.TagId)).Count();