sql-server - SQL Server 2000 : Ideas for performing concatenation aggregation subquery

标签 sql-server sql-server-2000 aggregate concatenation string-concatenation

我有一个查询返回我想要的行,例如

QuestionID  QuestionTitle  UpVotes  DownVotes  
==========  =============  =======  =========  
2142075     Win32: Cre...        0          0  
2232727     Win32: How...        2          0  
1870139     Wondows Ae...       12          0  

现在我想要返回一个,其中包含以逗号分隔的“作者”列表(例如原始发布者和编辑者)。例如:

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


假装

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

如果有多个作者,那么我会向用户显示一个省略号(“...”),以表明有多个作者。例如用户会看到:

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, …

这效果很好,因为通常问题不会被编辑 - 这意味着我完美支持 99% 的情况,而 1% 的情况只有一半-assed 也是如此。


线程重新查询

作为一个更复杂且容易出现错误的解决方案,我正在考虑迭代显示的列表,并为列表中的每个“问题”启动线程池工作线程,执行查询数据库以获取作者列表,然后在内存中聚合该列表。这意味着该列表首先填充( native )应用程序。然后我会发出几千个单独的查询。

但这会非常、非常、非常、缓慢。更不用说漏洞百出,因为这将是线程工作。


是啊是啊

亚当机械师says quite plainly :

Don't concatenate rows into delimited strings in SQL Server. Do it client side.

告诉我怎么做,我就去做。


/哭泣

任何人都可以想到一个更好的解决方案,它比我原来的“TOP 1 plus ellipses”解决方案一样快(比如说......在一个数量级内)?

例如,有没有办法返回结果集,其中到达行有关联的结果集?因此,对于每个“主”行,我可以获得包含列表的“详细”结果集。


最佳答案代码

Cade's链接至Adam Machanic's solution我喜欢最好的。一个用户定义的函数,似乎是通过魔法来操作的:

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

T-SQL 用法为:

SELECT QuestionID, QuestionTitle, UpVotes, DownVotes, dbo.ConcatAuthors(AuthorID)
FROM Questions

最佳答案

看看这些文章:

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 需要在作为第一个行集返回的同一集上打开一个游标,并按顺序运行多个选择以生成所有子行集。这是我已经完成的一项技术,但仅限于实际需要所有数据的情况(例如,在完全填充的 TreeView 中)。

无论人们怎么说,在客户端执行此操作通常会浪费大量带宽,因为返回所有行并在客户端执行循环和中断意味着正在传输大量相同的列每行的开头只是为了获取行末尾的变化列。

无论您在何处执行此操作,都应该根据您的用例做出明智的决定

关于sql-server - SQL Server 2000 : Ideas for performing concatenation aggregation subquery,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2410474/

相关文章:

sql - 如何在不创建函数的情况下删除 SQL 中的非字母数字字符?

sql-server - SSIS 传输数据库任务神秘错误消息 0x80131500

sql - 将表达式转换为数据类型 int 以进行基本统计时发生算术溢出错误

sql - 如何过滤查询以仅显示无法将列转换为 int 的结果

c++ - 使用聚合初始化列表优于构造函数的优势?

mysql - 使用aggregate和union all时我的SQL查询结果问题

c# - 使用 NHibernate 函数通过 QueryOver 过滤结果

jdbc - SQL Server 2000 JDBC 驱动程序

sql-server - MS-SQL Server 2000慢速全文本索引

sql - 如何使用 GROUP BY 连接 MySQL 中的字符串?