Ian*_*oyd 7 sql-server aggregate sql-server-2000 concatenation string-concatenation
我有一个返回我想要的行的查询,例如
QuestionID QuestionTitle UpVotes DownVotes
========== ============= ======= =========
2142075 Win32: Cre... 0 0
2232727 Win32: How... 2 0
1870139 Wondows Ae... 12 0
Run Code Online (Sandbox Code Playgroud)
现在我希望返回一个列,其中包含逗号分隔的" 作者 " 列表(例如原始海报和编辑).例如:
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
如果有多个作者,那么我向用户显示一个省略号("..."),表示有多个.例如,用户会看到:
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, …
Run Code Online (Sandbox Code Playgroud)
这样做效果很好,因为通常一个问题不会被编辑 - 这意味着我完全支持99%的情况,而1%的情况只有一半-也是.
作为一个更复杂,容易出错的解决方案,我正在考虑迭代显示的列表,并为列表中的每个" 问题 " 启动线程池工作线程,对数据库执行查询以获取作者列表,然后在内存中聚合列表.这意味着列表首先填充(本机)应用程序.然后我发出几千个单独的查询.
但那将是可怕的,可怕的,非常的,缓慢的.更不用说bug了,因为它将是线程工作.
亚当机械师说得很明白:
不要将行连接到SQL Server中的分隔字符串.做客户端.
告诉我怎么做,我会做的.
任何人都可以想到一个更好的解决方案,就像我原来的"TOP 1加省略号"解决方案一样快(比如......在一个数量级内)?
例如,有没有办法返回结果集,其中到达行有一个关联的结果集?因此,对于每个"主"行,我可以获得包含列表的"详细信息"结果集.
Cade与Adam Machanic解决方案的链接我最喜欢.用户定义的函数,似乎通过魔术操作:
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
Run Code Online (Sandbox Code Playgroud)
使用T-SQL:
SELECT QuestionID, QuestionTitle, UpVotes, DownVotes, dbo.ConcatAuthors(AuthorID)
FROM Questions
Run Code Online (Sandbox Code Playgroud)
看看这些文章:
http://dataeducation.com/rowset-string-concatenation-which-method-is-best/
http://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/(请参阅响应中 Phil Factor 的交叉联接解决方案 - 这将在 SQL Server 2000 中工作)
显然,在 SQL Server 2005 中,FOR XML 技巧是最简单、最灵活且通常性能最高的。
至于为每行返回一个行集,如果由于某种原因您仍然想这样做,您可以在存储过程中执行此操作,但客户端将需要消耗第一个行集中的所有行,然后转到下一个行集并将其与第一个行集中的第一行关联起来,等等。您的 SP 需要在作为第一个行集返回的同一集上打开一个游标,并按顺序运行多个选择以生成所有子行集。这是我已经完成的一项技术,但仅限于实际需要所有数据的情况(例如,在完全填充的树视图中)。
不管人们怎么说,在客户端执行此操作通常会浪费大量带宽,因为返回所有行并在客户端执行循环和中断意味着在开始时会传输大量相同的列。每行只是为了获取行末尾的变化列。
无论您在何处执行此操作,都应该根据您的用例做出明智的决定。
| 归档时间: |
|
| 查看次数: |
9218 次 |
| 最近记录: |