我有一个返回我想要的行的查询,例如
QuestionID QuestionTitle UpVotes DownVotes ========== ============= ======= ========= 2142075 Win32: Cre... 0 0 2232727 Win32: How... 2 0 1870139 Wondows Ae... 12 0@H_301_4@现在我希望返回一个列,其中包含逗号分隔的“作者”列表(例如原始海报和编辑).例如.:
QuestionID QuestionTitle UpVotes DownVotes Authors ========== ============= ======= ========= ========== 2142075 Win32: Cre... 0 0 Ian Boyd 2232727 Win32: How... 2 0 Ian Boyd,roygbiv 1870139 Wondows Ae... 12 0 Ian Boyd,Aaron Klotz,Jason Diller,danbystrom@H_301_4@作假 @H_301_4@sql Server 2000没有CONCAT(AuthorName,’,’)聚合操作,我一直伪造它 – 为TOP 1作者和作者计数执行简单的子选择.
QuestionID QuestionTitle UpVotes DownVotes FirstAuthor AuthorCount ========== ============= ======= ========= =========== =========== 2142075 Win32: Cre... 0 0 Ian Boyd 1 2232727 Win32: How... 2 0 Ian Boyd 2 1870139 Wondows Ae... 12 0 Ian Boyd 3@H_301_4@如果有多个作者,那么我向用户显示一个省略号(“…”),表示有多个.例如用户会看到:
QuestionID QuestionTitle UpVotes DownVotes Authors ========== ============= ======= ========= ========== 2142075 Win32: Cre... 0 0 Ian Boyd 2232727 Win32: How... 2 0 Ian Boyd,… 1870139 Wondows Ae... 12 0 Ian Boyd,…@H_301_4@这很有效,因为通常一个问题不会被编辑 – 这意味着我完全支持99%的情况,1%的情况也只有一半. @H_301_4@线程重新查询 @H_301_4@作为一个更复杂,容易出错的解决方案,我正在考虑迭代显示的列表,并为列表中的每个“问题”启动线程池工作线程,对数据库执行查询以获取作者列表,然后在内存中聚合列表.这意味着列表首先填充(本机)应用程序.然后我发出几千个单独的查询. @H_301_4@但那将是可怕的,可怕的,非常的,缓慢的.更不用说bug-riddled,因为它将是线程工作. @H_301_4@耶耶耶 @H_301_4@Adam Mechanic says quite plainly:
@H_301_4@Don’t concatenate rows into delimited@H_301_4@告诉我怎么做,我会做的. @H_301_4@/哭 @H_301_4@任何人都可以想到一个更好的解决方案,就像我原来的“TOP 1 plus ellipses”解决方案一样快(比如说…在一个数量级内)? @H_301_4@例如,有没有办法返回结果集,其中到达行有关联的结果集?因此,对于每个“主”行,我可以获得包含列表的“详细信息”结果集. @H_301_4@代码为最佳答案 @H_301_4@Cade’s链接到Adam Machanic’s solution我最喜欢.用户定义的函数,似乎通过魔术操作:
strings in sql Server. Do it client
side.
CREATE FUNCTION dbo.ConcatAuthors(@QuestionID int) RETURNS VARCHAR(8000) AS BEGIN DECLARE @Output VARCHAR(8000) SET @Output = '' SELECT @Output = CASE @Output WHEN '' THEN AuthorName ELSE @Output + ',' + AuthorName END FROM ( SELECT QuestionID,AuthorName,QuestionDate AS AuthorDate FROM Questions UNION SELECT QuestionID,EditorName,EditDate FROM QuestionEdits ) dt WHERE dt.QuestionID = @QuestionID ORDER BY AuthorDate RETURN @Output END@H_301_4@使用T-sql:
SELECT QuestionID,QuestionTitle,UpVotes,DownVotes,dbo.ConcatAuthors(AuthorID) FROM Questions
解决方法
看看这些文章:
@H_301_4@http://sqlblog.com/blogs/adam_machanic/archive/2006/07/12/rowset-string-concatenation-which-method-is-best.aspx
@H_301_4@http://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/(请参阅响应中的Phil Factor的交叉连接解决方案 – 这将在sql Server 2000中有效)
@H_301_4@显然在sql Server 2005中,FOR XML技巧最简单,最灵活,通常效率最高.
@H_301_4@至于为每一行返回行集,如果由于某种原因仍然想要这样做,可以在存储过程中执行此操作,但客户端需要使用第一行集中的所有行,然后转到下一行rowset并将其与第一个行集中的第一行相关联等.您的SP需要在它作为第一个行集返回的同一个集合上打开一个游标,并按顺序运行多个选择以生成所有子行集.这是我已经完成的一项技术,但仅限于实际需要所有数据的地方(例如,在完全填充的树视图中).
@H_301_4@无论人们怎么说,做客户端通常都是浪费带宽,因为返回所有行并在客户端进行循环和中断意味着在开始时传输了大量相同的列.每行只是为了获得行尾的更改列.
@H_301_4@无论您在何处进行,都应根据您的使用案例做出明智的决定.