之前寫了一篇文章:關於SQL函數效率的一些測試與思考,在當中提到了將數據庫中一對多關系轉換為一對一關系顯示的兩種方法:第一種方法是在數據庫中寫一個函數,第二種方法為在程序中獲取表Class與表Student所有數據,然后對比ClassID。
那么除了這兩種方法,還有沒有更快、更好的方法呢?在這里我再介紹兩種方法與大家分享、討論
閑話不多說,下面進入正文。還是那兩張表
Student:
ID | StuName | ClassID |
1 | 張三 | 1 |
2 | 張三 | 2 |
3 | 李四 | 1 |
4 | 王五 | 2 |
5 | 王五 | 1 |
Class:
ID | ClassName |
1 | 數學 |
2 | 語文 |
3 | 英語 |
想要獲得的數據效果為
ID | ClassName | StuName |
1 | 數學 | 張三,李四,王五 |
2 | 語文 | 張三,王五 |
3 | 英語 | NULL |
第三種方法:使用SQL函數stuff
SQL語句如下
SELECT C.ID, C.ClassName,stuff((select ',' + S.StuName from dbo.Student S where S.ClassID = C.ID for xml path('')),1,1,'')as stuName FROM Class C
將第三種方法與第二種方法(在程序中獲取表Class與表Student所有數據,然后對比ClassID)對比效率,輸出結果如下:
00:00:00.5497196
00:00:00.3517834
效率比1.562665
=============================
00:00:01.0181020
00:00:00.7060913
效率比1.441884
=============================
00:00:01.4912831
00:00:01.0682834
效率比1.395962
=============================
00:00:01.9636678
00:00:01.4199062
效率比1.382956
=============================
00:00:02.4391574
00:00:01.7712431
效率比1.377088
=============================
00:00:02.9111560
00:00:02.1255719
效率比1.369587
=============================
00:00:03.3923697
00:00:02.5069699
效率比1.353175
=============================
00:00:03.8671226
00:00:02.8594541
效率比1.352399
=============================
00:00:04.3314012
00:00:03.2064415
效率比1.350844
=============================
00:00:04.8019142
00:00:03.5546490
效率比1.350883
=============================
第一個時間為第二種方法的執行時間,第二個時間為第三種方法執行時間。每種方法循環了10次以確保數據准確性
關於測試程序代碼在之前的文章中有提到,改一下SQL語句就可以使用了
數據結果顯示第三種方法要優秀不少。至於為什么第三種方法快,我心里已經有了個大致的想法,不過因為太難表述了,就懶得浪費口水說了,大家記住結論就好了
接下來介紹第四種方法:在SQL中加載程序集,在查詢時調用程序集
加載程序集的方法有些難以表述,感興趣的朋友可以自己去查找相關資料。在此我貼出主要代碼:

/// <summary>
/// The variable that holds the intermediate result of the concatenation
/// </summary>
private StringBuilder intermediateResult;
/// <summary>
/// Initialize the internal data structures
/// </summary>
public void Init()
{
this.intermediateResult = new StringBuilder();
}
/// <summary>
/// Accumulate the next value, not if the value is null
/// </summary>
/// <param name="value"></param>
public void Accumulate(SqlString value)
{
if (value.IsNull)
{
return;
}
this.intermediateResult.Append(value.Value).Append(',');
}
/// <summary>
/// Merge the partially computed aggregate with this aggregate.
/// </summary>
/// <param name="other"></param>
public void Merge(Concatenate other)
{
this.intermediateResult.Append(other.intermediateResult);
}
/// <summary>
/// Called at the end of aggregation, to return the results of the aggregation.
/// </summary>
/// <returns></returns>
public SqlString Terminate()
{
string output = string.Empty;
//delete the trailing comma, if any
if (this.intermediateResult != null
&& this.intermediateResult.Length > 0)
{
output = this.intermediateResult.ToString(0, this.intermediateResult.Length - 1);
}
return new SqlString(output);
}
public void Read(BinaryReader r)
{
intermediateResult = new StringBuilder(r.ReadString());
}
public void Write(BinaryWriter w)
{
w.Write(this.intermediateResult.ToString());
}
這個方法比第三種方法快得不多,大概只有5%到10%的性能提升,但是這種方法十分優雅,我竊以為這種方法是解決一對多關系轉換一對一方法中最好的方法
PS:最近太懶了,都沒有來博客園寫東西。罪過罪過
再PS:想吐槽一下,最近園子里幾個小妹子寫的生活上的雜七雜八的東西居然引起了那么多人的追捧,而真正的技術貼卻是無人問津,不得不說是一種悲哀
再再PS:歡迎留言討論,歡迎轉載。不足之處望海涵