2012-08-22 55 views
2

我买了两个数据表,列出如下:逗号分隔结果集+ SQL查询

表1:学生

enter image description here

表2:主题

enter image description here

我需要输出为:

enter image description here

我这来达到的,使用了XML路径下查询

代码:

WITH cte 
     AS (SELECT Stu.Student_Id , 
        Stu.Student_Name , 
        (SELECT Sub.[Subject] + ',' 
         FROM  [Subject] AS Sub 
         WHERE  Sub.Student_Id = Stu.Student_Id 
         ORDER BY Sub.[Subject] 
        FOR 
         XML PATH('') 
        ) AS [Subjects] 
      FROM  dbo.Student AS Stu 
     ) 
SELECT Student_id [Student Id] , 
     student_name [Student Name] , 
     SUBSTRING(Subjects, 1, (LEN(Subjects) - 1)) AS [Student Subjects] 
FROM cte 

我的问题是有没有更好的方式来做到这一点,而不使用XML路径?

回答

2

这是一个非常好的方法,并已被接受。有几种方法,这blog post描述很多他们。

存在的一个有趣的方法是使用CLR为您完成工作,这将显着降低运行外部代码的权衡的查询的复杂性。下面是组件中类可能的样例。

using System; 
using System.Collections.Generic; 
using System.Data.SqlTypes; 
using System.IO; 
using Microsoft.SqlServer.Server; 

[Serializable] 
[SqlUserDefinedAggregate(Format.UserDefined, MaxByteSize=8000)] 
public struct strconcat : IBinarySerialize{ 

    private List values; 

    public void Init() { 
     this.values = new List(); 
    } 

    public void Accumulate(SqlString value) { 
     this.values.Add(value.Value); 
    } 

    public void Merge(strconcat value) { 
     this.values.AddRange(value.values.ToArray()); 
    } 

    public SqlString Terminate() { 
     return new SqlString(string.Join(", ", this.values.ToArray())); 
    } 

    public void Read(BinaryReader r) { 
     int itemCount = r.ReadInt32(); 
     this.values = new List(itemCount); 
     for (int i = 0; i <= itemCount - 1; i++) { 
      this.values.Add(r.ReadString()); 
     } 
    } 

    public void Write(BinaryWriter w) { 
     w.Write(this.values.Count); 
     foreach (string s in this.values)  { 
      w.Write(s); 
     } 
    } 
} 

而这将网络查询更像这样。

SELECT CategoryId, 
      dbo.strconcat(ProductName) 
     FROM Products 
    GROUP BY CategoryId ; 

这显然比较简单一些。拿它来做它的价值:)

美好的一天!